vserver 1.9.5.x5
[linux-2.6.git] / arch / um / kernel / syscall_kern.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 "asm/ipc.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 um_mount(char __user * dev_name, char __user * dir_name,
33               char __user * type, unsigned long new_flags, void __user * data)
34 {
35         return(sys_mount(dev_name, dir_name, type, new_flags, data));
36 }
37
38 long sys_fork(void)
39 {
40         long ret;
41
42         current->thread.forking = 1;
43         ret = do_fork(SIGCHLD, 0, NULL, 0, NULL, NULL);
44         current->thread.forking = 0;
45         return(ret);
46 }
47
48 long sys_vfork(void)
49 {
50         long ret;
51
52         current->thread.forking = 1;
53         ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, NULL, 0, NULL,
54                       NULL);
55         current->thread.forking = 0;
56         return(ret);
57 }
58
59 /* common code for old and new mmaps */
60 long sys_mmap2(unsigned long addr, unsigned long len,
61                unsigned long prot, unsigned long flags,
62                unsigned long fd, unsigned long pgoff)
63 {
64         long error = -EBADF;
65         struct file * file = NULL;
66
67         flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
68         if (!(flags & MAP_ANONYMOUS)) {
69                 file = fget(fd);
70                 if (!file)
71                         goto out;
72         }
73
74         down_write(&current->mm->mmap_sem);
75         error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
76         up_write(&current->mm->mmap_sem);
77
78         if (file)
79                 fput(file);
80  out:
81         return error;
82 }
83
84 long old_mmap(unsigned long addr, unsigned long len,
85               unsigned long prot, unsigned long flags,
86               unsigned long fd, unsigned long offset)
87 {
88         long err = -EINVAL;
89         if (offset & ~PAGE_MASK)
90                 goto out;
91
92         err = sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
93  out:
94         return err;
95 }
96 /*
97  * sys_pipe() is the normal C calling standard for creating
98  * a pipe. It's not the way unix traditionally does this, though.
99  */
100 long sys_pipe(unsigned long __user * fildes)
101 {
102         int fd[2];
103         long error;
104
105         error = do_pipe(fd);
106         if (!error) {
107                 if (copy_to_user(fildes, fd, sizeof(fd)))
108                         error = -EFAULT;
109         }
110         return error;
111 }
112
113
114 long sys_uname(struct old_utsname * name)
115 {
116         long err;
117         if (!name)
118                 return -EFAULT;
119         down_read(&uts_sem);
120         err=copy_to_user(name, vx_new_utsname(), sizeof (*name));
121         up_read(&uts_sem);
122         return err?-EFAULT:0;
123 }
124
125 long sys_olduname(struct oldold_utsname * name)
126 {
127         long error;
128         struct new_utsname *ptr;
129
130         if (!name)
131                 return -EFAULT;
132         if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
133                 return -EFAULT;
134   
135         down_read(&uts_sem);
136         
137         ptr = vx_new_utsname();
138         error = __copy_to_user(&name->sysname,ptr->sysname,
139                                __OLD_UTS_LEN);
140         error |= __put_user(0,name->sysname+__OLD_UTS_LEN);
141         error |= __copy_to_user(&name->nodename,ptr->nodename,
142                                 __OLD_UTS_LEN);
143         error |= __put_user(0,name->nodename+__OLD_UTS_LEN);
144         error |= __copy_to_user(&name->release,ptr->release,
145                                 __OLD_UTS_LEN);
146         error |= __put_user(0,name->release+__OLD_UTS_LEN);
147         error |= __copy_to_user(&name->version,ptr->version,
148                                 __OLD_UTS_LEN);
149         error |= __put_user(0,name->version+__OLD_UTS_LEN);
150         error |= __copy_to_user(&name->machine,ptr->machine,
151                                 __OLD_UTS_LEN);
152         error |= __put_user(0,name->machine+__OLD_UTS_LEN);
153         
154         up_read(&uts_sem);
155         
156         error = error ? -EFAULT : 0;
157
158         return error;
159 }
160
161 long execute_syscall(void *r)
162 {
163         return(CHOOSE_MODE_PROC(execute_syscall_tt, execute_syscall_skas, r));
164 }
165
166 DEFINE_SPINLOCK(syscall_lock);
167
168 static int syscall_index = 0;
169
170 int next_syscall_index(int limit)
171 {
172         int ret;
173
174         spin_lock(&syscall_lock);
175         ret = syscall_index;
176         if(++syscall_index == limit)
177                 syscall_index = 0;
178         spin_unlock(&syscall_lock);
179         return(ret);
180 }
181
182 /*
183  * Overrides for Emacs so that we follow Linus's tabbing style.
184  * Emacs will notice this stuff at the end of the file and automatically
185  * adjust the settings for this buffer only.  This must remain at the end
186  * of the file.
187  * ---------------------------------------------------------------------------
188  * Local variables:
189  * c-file-style: "linux"
190  * End:
191  */