Merge to Fedora kernel-2.6.18-1.2255_FC5-vs2.0.2.2-rc9 patched with stable patch...
[linux-2.6.git] / arch / um / kernel / syscall.c
1 /*
2  * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
3  * Licensed under the GPL
4  */
5
6 #include "linux/sched.h"
7 #include "linux/file.h"
8 #include "linux/smp_lock.h"
9 #include "linux/mm.h"
10 #include "linux/utsname.h"
11 #include "linux/msg.h"
12 #include "linux/shm.h"
13 #include "linux/sys.h"
14 #include "linux/syscalls.h"
15 #include "linux/unistd.h"
16 #include "linux/slab.h"
17 #include "linux/utime.h"
18 #include <linux/vs_base.h>
19 #include <linux/vs_cvirt.h>
20
21 #include "asm/mman.h"
22 #include "asm/uaccess.h"
23 #include "kern_util.h"
24 #include "user_util.h"
25 #include "sysdep/syscalls.h"
26 #include "mode_kern.h"
27 #include "choose-mode.h"
28
29 /*  Unlocked, I don't care if this is a bit off */
30 int nsyscalls = 0;
31
32 long sys_fork(void)
33 {
34         long ret;
35
36         current->thread.forking = 1;
37         ret = do_fork(SIGCHLD, UPT_SP(&current->thread.regs.regs),
38                       &current->thread.regs, 0, NULL, NULL);
39         current->thread.forking = 0;
40         return(ret);
41 }
42
43 long sys_vfork(void)
44 {
45         long ret;
46
47         current->thread.forking = 1;
48         ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
49                       UPT_SP(&current->thread.regs.regs),
50                       &current->thread.regs, 0, NULL, NULL);
51         current->thread.forking = 0;
52         return(ret);
53 }
54
55 /* common code for old and new mmaps */
56 long sys_mmap2(unsigned long addr, unsigned long len,
57                unsigned long prot, unsigned long flags,
58                unsigned long fd, unsigned long pgoff)
59 {
60         long error = -EBADF;
61         struct file * file = NULL;
62
63         flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
64         if (!(flags & MAP_ANONYMOUS)) {
65                 file = fget(fd);
66                 if (!file)
67                         goto out;
68         }
69
70         down_write(&current->mm->mmap_sem);
71         error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
72         up_write(&current->mm->mmap_sem);
73
74         if (file)
75                 fput(file);
76  out:
77         return error;
78 }
79
80 long old_mmap(unsigned long addr, unsigned long len,
81               unsigned long prot, unsigned long flags,
82               unsigned long fd, unsigned long offset)
83 {
84         long err = -EINVAL;
85         if (offset & ~PAGE_MASK)
86                 goto out;
87
88         err = sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
89  out:
90         return err;
91 }
92 /*
93  * sys_pipe() is the normal C calling standard for creating
94  * a pipe. It's not the way unix traditionally does this, though.
95  */
96 long sys_pipe(unsigned long __user * fildes)
97 {
98         int fd[2];
99         long error;
100
101         error = do_pipe(fd);
102         if (!error) {
103                 if (copy_to_user(fildes, fd, sizeof(fd)))
104                         error = -EFAULT;
105         }
106         return error;
107 }
108
109
110 long sys_uname(struct old_utsname __user * name)
111 {
112         long err;
113         if (!name)
114                 return -EFAULT;
115         down_read(&uts_sem);
116         err = copy_to_user(name, vx_new_utsname(), sizeof (*name));
117         up_read(&uts_sem);
118         return err?-EFAULT:0;
119 }
120
121 long sys_olduname(struct oldold_utsname __user * name)
122 {
123         long error;
124         struct new_utsname *ptr;
125
126         if (!name)
127                 return -EFAULT;
128         if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
129                 return -EFAULT;
130
131         down_read(&uts_sem);
132
133         ptr = vx_new_utsname();
134         error = __copy_to_user(&name->sysname,ptr->sysname,
135                                __OLD_UTS_LEN);
136         error |= __put_user(0,name->sysname+__OLD_UTS_LEN);
137         error |= __copy_to_user(&name->nodename,ptr->nodename,
138                                 __OLD_UTS_LEN);
139         error |= __put_user(0,name->nodename+__OLD_UTS_LEN);
140         error |= __copy_to_user(&name->release,ptr->release,
141                                 __OLD_UTS_LEN);
142         error |= __put_user(0,name->release+__OLD_UTS_LEN);
143         error |= __copy_to_user(&name->version,ptr->version,
144                                 __OLD_UTS_LEN);
145         error |= __put_user(0,name->version+__OLD_UTS_LEN);
146         error |= __copy_to_user(&name->machine,ptr->machine,
147                                 __OLD_UTS_LEN);
148         error |= __put_user(0,name->machine+__OLD_UTS_LEN);
149
150         up_read(&uts_sem);
151
152         error = error ? -EFAULT : 0;
153
154         return error;
155 }
156
157 DEFINE_SPINLOCK(syscall_lock);
158
159 static int syscall_index = 0;
160
161 int next_syscall_index(int limit)
162 {
163         int ret;
164
165         spin_lock(&syscall_lock);
166         ret = syscall_index;
167         if(++syscall_index == limit)
168                 syscall_index = 0;
169         spin_unlock(&syscall_lock);
170         return(ret);
171 }