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