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
index 1731d90..85fb0f9 100644 (file)
 /*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
+#include "linux/sched.h"
+#include "linux/file.h"
+#include "linux/smp_lock.h"
+#include "linux/mm.h"
+#include "linux/utsname.h"
+#include "linux/msg.h"
+#include "linux/shm.h"
+#include "linux/sys.h"
+#include "linux/syscalls.h"
+#include "linux/unistd.h"
+#include "linux/slab.h"
+#include "linux/utime.h"
+#include <linux/vs_cvirt.h>
+
+#include "asm/mman.h"
+#include "asm/uaccess.h"
 #include "kern_util.h"
-#include "syscall.h"
-#include "os.h"
+#include "user_util.h"
+#include "sysdep/syscalls.h"
+#include "mode_kern.h"
+#include "choose-mode.h"
+
+/*  Unlocked, I don't care if this is a bit off */
+int nsyscalls = 0;
 
-struct {
-       int syscall;
-       int pid;
-       long result;
-       unsigned long long start;
-       unsigned long long end;
-} syscall_record[1024];
+long sys_fork(void)
+{
+       long ret;
+
+       current->thread.forking = 1;
+       ret = do_fork(SIGCHLD, UPT_SP(&current->thread.regs.regs),
+                     &current->thread.regs, 0, NULL, NULL);
+       current->thread.forking = 0;
+       return(ret);
+}
+
+long sys_vfork(void)
+{
+       long ret;
+
+       current->thread.forking = 1;
+       ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
+                     UPT_SP(&current->thread.regs.regs),
+                     &current->thread.regs, 0, NULL, NULL);
+       current->thread.forking = 0;
+       return(ret);
+}
 
-int record_syscall_start(int syscall)
+/* common code for old and new mmaps */
+long sys_mmap2(unsigned long addr, unsigned long len,
+              unsigned long prot, unsigned long flags,
+              unsigned long fd, unsigned long pgoff)
 {
-       int max, index;
+       long error = -EBADF;
+       struct file * file = NULL;
 
-       max = sizeof(syscall_record)/sizeof(syscall_record[0]);
-       index = next_syscall_index(max);
+       flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+       if (!(flags & MAP_ANONYMOUS)) {
+               file = fget(fd);
+               if (!file)
+                       goto out;
+       }
 
-       syscall_record[index].syscall = syscall;
-       syscall_record[index].pid = current_pid();
-       syscall_record[index].result = 0xdeadbeef;
-       syscall_record[index].start = os_nsecs();
-       return(index);
+       down_write(&current->mm->mmap_sem);
+       error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+       up_write(&current->mm->mmap_sem);
+
+       if (file)
+               fput(file);
+ out:
+       return error;
 }
 
-void record_syscall_end(int index, long result)
+long old_mmap(unsigned long addr, unsigned long len,
+             unsigned long prot, unsigned long flags,
+             unsigned long fd, unsigned long offset)
 {
-       syscall_record[index].result = result;
-       syscall_record[index].end = os_nsecs();
+       long err = -EINVAL;
+       if (offset & ~PAGE_MASK)
+               goto out;
+
+       err = sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
+ out:
+       return err;
+}
+/*
+ * sys_pipe() is the normal C calling standard for creating
+ * a pipe. It's not the way unix traditionally does this, though.
+ */
+long sys_pipe(unsigned long __user * fildes)
+{
+        int fd[2];
+        long error;
+
+        error = do_pipe(fd);
+        if (!error) {
+               if (copy_to_user(fildes, fd, sizeof(fd)))
+                        error = -EFAULT;
+        }
+        return error;
+}
+
+
+long sys_uname(struct old_utsname __user * name)
+{
+       long err;
+       if (!name)
+               return -EFAULT;
+       down_read(&uts_sem);
+       err = copy_to_user(name, vx_new_utsname(), sizeof (*name));
+       up_read(&uts_sem);
+       return err?-EFAULT:0;
+}
+
+long sys_olduname(struct oldold_utsname __user * name)
+{
+       long error;
+       struct new_utsname *ptr;
+
+       if (!name)
+               return -EFAULT;
+       if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
+               return -EFAULT;
+
+       down_read(&uts_sem);
+
+       ptr = vx_new_utsname();
+       error = __copy_to_user(&name->sysname,ptr->sysname,
+                              __OLD_UTS_LEN);
+       error |= __put_user(0,name->sysname+__OLD_UTS_LEN);
+       error |= __copy_to_user(&name->nodename,ptr->nodename,
+                               __OLD_UTS_LEN);
+       error |= __put_user(0,name->nodename+__OLD_UTS_LEN);
+       error |= __copy_to_user(&name->release,ptr->release,
+                               __OLD_UTS_LEN);
+       error |= __put_user(0,name->release+__OLD_UTS_LEN);
+       error |= __copy_to_user(&name->version,ptr->version,
+                               __OLD_UTS_LEN);
+       error |= __put_user(0,name->version+__OLD_UTS_LEN);
+       error |= __copy_to_user(&name->machine,ptr->machine,
+                               __OLD_UTS_LEN);
+       error |= __put_user(0,name->machine+__OLD_UTS_LEN);
+
+       up_read(&uts_sem);
+
+       error = error ? -EFAULT : 0;
+
+       return error;
+}
+
+DEFINE_SPINLOCK(syscall_lock);
+
+static int syscall_index = 0;
+
+int next_syscall_index(int limit)
+{
+       int ret;
+
+       spin_lock(&syscall_lock);
+       ret = syscall_index;
+       if(++syscall_index == limit)
+               syscall_index = 0;
+       spin_unlock(&syscall_lock);
+       return(ret);
 }