linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / arch / um / sys-x86_64 / syscalls.c
1 /*
2  * Copyright 2003 PathScale, Inc.
3  *
4  * Licensed under the GPL
5  */
6
7 #include "linux/linkage.h"
8 #include "linux/slab.h"
9 #include "linux/shm.h"
10 #include "linux/utsname.h"
11 #include "linux/personality.h"
12 #include "linux/sched.h"
13 #include "linux/vs_cvirt.h"
14 #include "asm/uaccess.h"
15 #define __FRAME_OFFSETS
16 #include "asm/ptrace.h"
17 #include "asm/unistd.h"
18 #include "asm/prctl.h" /* XXX This should get the constants from libc */
19 #include "choose-mode.h"
20 #include "kern.h"
21
22 asmlinkage long sys_uname64(struct new_utsname __user * name)
23 {
24         int err;
25         down_read(&uts_sem);
26         err = copy_to_user(name, vx_new_utsname(), sizeof (*name));
27         up_read(&uts_sem);
28         if (personality(current->personality) == PER_LINUX32)
29                 err |= copy_to_user(&name->machine, "i686", 5);
30         return err ? -EFAULT : 0;
31 }
32
33 #ifdef CONFIG_MODE_TT
34 extern long arch_prctl(int code, unsigned long addr);
35
36 static long arch_prctl_tt(int code, unsigned long addr)
37 {
38         unsigned long tmp;
39         long ret;
40
41         switch(code){
42         case ARCH_SET_GS:
43         case ARCH_SET_FS:
44                 ret = arch_prctl(code, addr);
45                 break;
46         case ARCH_GET_FS:
47         case ARCH_GET_GS:
48                 ret = arch_prctl(code, (unsigned long) &tmp);
49                 if(!ret)
50                         ret = put_user(tmp, &addr);
51                 break;
52         default:
53                 ret = -EINVAL;
54                 break;
55         }
56
57         return(ret);
58 }
59 #endif
60
61 #ifdef CONFIG_MODE_SKAS
62
63 /* XXX: Must also call arch_prctl in the host, beside saving the segment bases! */
64 static long arch_prctl_skas(int code, unsigned long addr)
65 {
66         long ret = 0;
67
68         switch(code){
69         case ARCH_SET_FS:
70                 current->thread.regs.regs.skas.regs[FS_BASE / sizeof(unsigned long)] = addr;
71                 break;
72         case ARCH_SET_GS:
73                 current->thread.regs.regs.skas.regs[GS_BASE / sizeof(unsigned long)] = addr;
74                 break;
75         case ARCH_GET_FS:
76                 ret = put_user(current->thread.regs.regs.skas.
77                                 regs[FS_BASE / sizeof(unsigned long)],
78                                 (unsigned long __user *)addr);
79                 break;
80         case ARCH_GET_GS:
81                 ret = put_user(current->thread.regs.regs.skas.
82                                 regs[GS_BASE / sizeof(unsigned long)],
83                                 (unsigned long __user *)addr);
84                 break;
85         default:
86                 ret = -EINVAL;
87                 break;
88         }
89
90         return(ret);
91 }
92 #endif
93
94 long sys_arch_prctl(int code, unsigned long addr)
95 {
96         return(CHOOSE_MODE_PROC(arch_prctl_tt, arch_prctl_skas, code, addr));
97 }
98
99 long sys_clone(unsigned long clone_flags, unsigned long newsp,
100                void __user *parent_tid, void __user *child_tid)
101 {
102         long ret;
103
104         if (!newsp)
105                 newsp = UPT_SP(&current->thread.regs.regs);
106         current->thread.forking = 1;
107         ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
108                       child_tid);
109         current->thread.forking = 0;
110         return(ret);
111 }