Add a set_rtc_mmss() handler for faster timekeeping.
[linux-2.6/linux-mips.git] / arch / mips / kernel / syscall.c
blobf6ca25bc648336e1e10493b96ccbfab724701631
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 - 2000 by Ralf Baechle
7 * Copyright (C) 2000 Silicon Graphics, Inc.
9 * TODO: Implement the compatibility syscalls.
10 * Don't waste that much memory for empty entries in the syscall
11 * table.
13 #undef CONF_PRINT_SYSCALLS
14 #undef CONF_DEBUG_IRIX
16 #include <linux/config.h>
17 #include <linux/compiler.h>
18 #include <linux/linkage.h>
19 #include <linux/mm.h>
20 #include <linux/smp.h>
21 #include <linux/smp_lock.h>
22 #include <linux/mman.h>
23 #include <linux/sched.h>
24 #include <linux/file.h>
25 #include <linux/slab.h>
26 #include <linux/utsname.h>
27 #include <linux/unistd.h>
28 #include <asm/branch.h>
29 #include <asm/offset.h>
30 #include <asm/ptrace.h>
31 #include <asm/signal.h>
32 #include <asm/shmparam.h>
33 #include <asm/uaccess.h>
35 extern asmlinkage void syscall_trace(void);
36 typedef asmlinkage int (*syscall_t)(void *a0,...);
37 extern asmlinkage int (*do_syscalls)(struct pt_regs *regs, syscall_t fun,
38 int narg);
39 extern syscall_t sys_call_table[];
40 extern unsigned char sys_narg_table[];
42 asmlinkage int sys_pipe(struct pt_regs regs)
44 int fd[2];
45 int error, res;
47 error = do_pipe(fd);
48 if (error) {
49 res = error;
50 goto out;
52 regs.regs[3] = fd[1];
53 res = fd[0];
54 out:
55 return res;
58 unsigned long shm_align_mask = PAGE_SIZE - 1; /* Sane caches */
60 #define COLOUR_ALIGN(addr,pgoff) \
61 ((((addr) + shm_align_mask) & ~shm_align_mask) + \
62 (((pgoff) << PAGE_SHIFT) & shm_align_mask))
64 unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
65 unsigned long len, unsigned long pgoff, unsigned long flags)
67 struct vm_area_struct * vmm;
68 int do_color_align;
70 if (flags & MAP_FIXED) {
72 * We do not accept a shared mapping if it would violate
73 * cache aliasing constraints.
75 if ((flags & MAP_SHARED) && (addr & shm_align_mask))
76 return -EINVAL;
77 return addr;
80 if (len > TASK_SIZE)
81 return -ENOMEM;
82 do_color_align = 0;
83 if (filp || (flags & MAP_SHARED))
84 do_color_align = 1;
85 if (addr) {
86 if (do_color_align)
87 addr = COLOUR_ALIGN(addr, pgoff);
88 else
89 addr = PAGE_ALIGN(addr);
90 vmm = find_vma(current->mm, addr);
91 if (TASK_SIZE - len >= addr &&
92 (!vmm || addr + len <= vmm->vm_start))
93 return addr;
95 addr = TASK_UNMAPPED_BASE;
96 if (do_color_align)
97 addr = COLOUR_ALIGN(addr, pgoff);
98 else
99 addr = PAGE_ALIGN(addr);
101 for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
102 /* At this point: (!vmm || addr < vmm->vm_end). */
103 if (TASK_SIZE - len < addr)
104 return -ENOMEM;
105 if (!vmm || addr + len <= vmm->vm_start)
106 return addr;
107 addr = vmm->vm_end;
108 if (do_color_align)
109 addr = COLOUR_ALIGN(addr, pgoff);
113 /* common code for old and new mmaps */
114 static inline long
115 do_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
116 unsigned long flags, unsigned long fd, unsigned long pgoff)
118 int error = -EBADF;
119 struct file * file = NULL;
121 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
122 if (!(flags & MAP_ANONYMOUS)) {
123 file = fget(fd);
124 if (!file)
125 goto out;
128 down_write(&current->mm->mmap_sem);
129 error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
130 up_write(&current->mm->mmap_sem);
132 if (file)
133 fput(file);
134 out:
135 return error;
138 asmlinkage unsigned long old_mmap(unsigned long addr, size_t len, int prot,
139 int flags, int fd, off_t offset)
141 int result;
143 result = -EINVAL;
144 if (offset & ~PAGE_MASK)
145 goto out;
147 result = do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
149 out:
150 return result;
153 asmlinkage long
154 sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
155 unsigned long flags, unsigned long fd, unsigned long pgoff)
157 return do_mmap2(addr, len, prot, flags, fd, pgoff);
160 save_static_function(sys_fork);
161 static_unused int _sys_fork(struct pt_regs regs)
163 return do_fork(SIGCHLD, regs.regs[29], &regs, 0, NULL, NULL);
167 save_static_function(sys_clone);
168 static_unused int _sys_clone(struct pt_regs regs)
170 unsigned long clone_flags;
171 unsigned long newsp;
172 int *parent_tidptr, *child_tidptr;
174 clone_flags = regs.regs[4];
175 newsp = regs.regs[5];
176 if (!newsp)
177 newsp = regs.regs[29];
178 parent_tidptr = (int *) regs.regs[6];
179 child_tidptr = (int *) regs.regs[7];
180 return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0,
181 parent_tidptr, child_tidptr);
185 * sys_execve() executes a new program.
187 asmlinkage int sys_execve(struct pt_regs regs)
189 int error;
190 char * filename;
192 filename = getname((char *) (long)regs.regs[4]);
193 error = PTR_ERR(filename);
194 if (IS_ERR(filename))
195 goto out;
196 error = do_execve(filename, (char **) (long)regs.regs[5],
197 (char **) (long)regs.regs[6], &regs);
198 putname(filename);
200 out:
201 return error;
205 * Compacrapability ...
207 asmlinkage int sys_uname(struct old_utsname * name)
209 if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
210 return 0;
211 return -EFAULT;
215 * Compacrapability ...
217 asmlinkage int sys_olduname(struct oldold_utsname * name)
219 int error;
221 if (!name)
222 return -EFAULT;
223 if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
224 return -EFAULT;
226 error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
227 error -= __put_user(0,name->sysname+__OLD_UTS_LEN);
228 error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
229 error -= __put_user(0,name->nodename+__OLD_UTS_LEN);
230 error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
231 error -= __put_user(0,name->release+__OLD_UTS_LEN);
232 error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
233 error -= __put_user(0,name->version+__OLD_UTS_LEN);
234 error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
235 error = __put_user(0,name->machine+__OLD_UTS_LEN);
236 error = error ? -EFAULT : 0;
238 return error;
242 * If we ever come here the user sp is bad. Zap the process right away.
243 * Due to the bad stack signaling wouldn't work.
244 * XXX kernel locking???
246 asmlinkage void bad_stack(void)
248 do_exit(SIGSEGV);
252 * Build the string table for the builtin "poor man's strace".
254 #ifdef CONF_PRINT_SYSCALLS
255 #define SYS(fun, narg) #fun,
256 static char *sfnames[] = {
257 #include "syscalls.h"
259 #endif
261 #if defined(CONFIG_BINFMT_IRIX) && defined(CONF_DEBUG_IRIX)
262 #define SYS(fun, narg) #fun,
263 static char *irix_sys_names[] = {
264 #include "irix5sys.h"
266 #endif