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