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