diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/x86_64/kernel/sys_x86_64.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/x86_64/kernel/sys_x86_64.c')
-rw-r--r-- | arch/x86_64/kernel/sys_x86_64.c | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/arch/x86_64/kernel/sys_x86_64.c b/arch/x86_64/kernel/sys_x86_64.c new file mode 100644 index 000000000000..477d8be57d64 --- /dev/null +++ b/arch/x86_64/kernel/sys_x86_64.c | |||
@@ -0,0 +1,173 @@ | |||
1 | /* | ||
2 | * linux/arch/x86_64/kernel/sys_x86_64.c | ||
3 | */ | ||
4 | |||
5 | #include <linux/errno.h> | ||
6 | #include <linux/sched.h> | ||
7 | #include <linux/syscalls.h> | ||
8 | #include <linux/mm.h> | ||
9 | #include <linux/smp.h> | ||
10 | #include <linux/smp_lock.h> | ||
11 | #include <linux/sem.h> | ||
12 | #include <linux/msg.h> | ||
13 | #include <linux/shm.h> | ||
14 | #include <linux/stat.h> | ||
15 | #include <linux/mman.h> | ||
16 | #include <linux/file.h> | ||
17 | #include <linux/utsname.h> | ||
18 | #include <linux/personality.h> | ||
19 | |||
20 | #include <asm/uaccess.h> | ||
21 | #include <asm/ia32.h> | ||
22 | |||
23 | /* | ||
24 | * sys_pipe() is the normal C calling standard for creating | ||
25 | * a pipe. It's not the way Unix traditionally does this, though. | ||
26 | */ | ||
27 | asmlinkage long sys_pipe(int __user *fildes) | ||
28 | { | ||
29 | int fd[2]; | ||
30 | int error; | ||
31 | |||
32 | error = do_pipe(fd); | ||
33 | if (!error) { | ||
34 | if (copy_to_user(fildes, fd, 2*sizeof(int))) | ||
35 | error = -EFAULT; | ||
36 | } | ||
37 | return error; | ||
38 | } | ||
39 | |||
40 | asmlinkage long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, | ||
41 | unsigned long fd, unsigned long off) | ||
42 | { | ||
43 | long error; | ||
44 | struct file * file; | ||
45 | |||
46 | error = -EINVAL; | ||
47 | if (off & ~PAGE_MASK) | ||
48 | goto out; | ||
49 | |||
50 | error = -EBADF; | ||
51 | file = NULL; | ||
52 | flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); | ||
53 | if (!(flags & MAP_ANONYMOUS)) { | ||
54 | file = fget(fd); | ||
55 | if (!file) | ||
56 | goto out; | ||
57 | } | ||
58 | down_write(¤t->mm->mmap_sem); | ||
59 | error = do_mmap_pgoff(file, addr, len, prot, flags, off >> PAGE_SHIFT); | ||
60 | up_write(¤t->mm->mmap_sem); | ||
61 | |||
62 | if (file) | ||
63 | fput(file); | ||
64 | out: | ||
65 | return error; | ||
66 | } | ||
67 | |||
68 | static void find_start_end(unsigned long flags, unsigned long *begin, | ||
69 | unsigned long *end) | ||
70 | { | ||
71 | #ifdef CONFIG_IA32_EMULATION | ||
72 | if (test_thread_flag(TIF_IA32)) { | ||
73 | *begin = TASK_UNMAPPED_32; | ||
74 | *end = IA32_PAGE_OFFSET; | ||
75 | } else | ||
76 | #endif | ||
77 | if (flags & MAP_32BIT) { | ||
78 | /* This is usually used needed to map code in small | ||
79 | model, so it needs to be in the first 31bit. Limit | ||
80 | it to that. This means we need to move the | ||
81 | unmapped base down for this case. This can give | ||
82 | conflicts with the heap, but we assume that glibc | ||
83 | malloc knows how to fall back to mmap. Give it 1GB | ||
84 | of playground for now. -AK */ | ||
85 | *begin = 0x40000000; | ||
86 | *end = 0x80000000; | ||
87 | } else { | ||
88 | *begin = TASK_UNMAPPED_64; | ||
89 | *end = TASK_SIZE; | ||
90 | } | ||
91 | } | ||
92 | |||
93 | unsigned long | ||
94 | arch_get_unmapped_area(struct file *filp, unsigned long addr, | ||
95 | unsigned long len, unsigned long pgoff, unsigned long flags) | ||
96 | { | ||
97 | struct mm_struct *mm = current->mm; | ||
98 | struct vm_area_struct *vma; | ||
99 | unsigned long start_addr; | ||
100 | unsigned long begin, end; | ||
101 | |||
102 | find_start_end(flags, &begin, &end); | ||
103 | |||
104 | if (len > end) | ||
105 | return -ENOMEM; | ||
106 | |||
107 | if (addr) { | ||
108 | addr = PAGE_ALIGN(addr); | ||
109 | vma = find_vma(mm, addr); | ||
110 | if (end - len >= addr && | ||
111 | (!vma || addr + len <= vma->vm_start)) | ||
112 | return addr; | ||
113 | } | ||
114 | addr = mm->free_area_cache; | ||
115 | if (addr < begin) | ||
116 | addr = begin; | ||
117 | start_addr = addr; | ||
118 | |||
119 | full_search: | ||
120 | for (vma = find_vma(mm, addr); ; vma = vma->vm_next) { | ||
121 | /* At this point: (!vma || addr < vma->vm_end). */ | ||
122 | if (end - len < addr) { | ||
123 | /* | ||
124 | * Start a new search - just in case we missed | ||
125 | * some holes. | ||
126 | */ | ||
127 | if (start_addr != begin) { | ||
128 | start_addr = addr = begin; | ||
129 | goto full_search; | ||
130 | } | ||
131 | return -ENOMEM; | ||
132 | } | ||
133 | if (!vma || addr + len <= vma->vm_start) { | ||
134 | /* | ||
135 | * Remember the place where we stopped the search: | ||
136 | */ | ||
137 | mm->free_area_cache = addr + len; | ||
138 | return addr; | ||
139 | } | ||
140 | addr = vma->vm_end; | ||
141 | } | ||
142 | } | ||
143 | |||
144 | asmlinkage long sys_uname(struct new_utsname __user * name) | ||
145 | { | ||
146 | int err; | ||
147 | down_read(&uts_sem); | ||
148 | err = copy_to_user(name, &system_utsname, sizeof (*name)); | ||
149 | up_read(&uts_sem); | ||
150 | if (personality(current->personality) == PER_LINUX32) | ||
151 | err |= copy_to_user(&name->machine, "i686", 5); | ||
152 | return err ? -EFAULT : 0; | ||
153 | } | ||
154 | |||
155 | asmlinkage long wrap_sys_shmat(int shmid, char __user *shmaddr, int shmflg) | ||
156 | { | ||
157 | unsigned long raddr; | ||
158 | return do_shmat(shmid,shmaddr,shmflg,&raddr) ?: (long)raddr; | ||
159 | } | ||
160 | |||
161 | asmlinkage long sys_time64(long __user * tloc) | ||
162 | { | ||
163 | struct timeval now; | ||
164 | int i; | ||
165 | |||
166 | do_gettimeofday(&now); | ||
167 | i = now.tv_sec; | ||
168 | if (tloc) { | ||
169 | if (put_user(i,tloc)) | ||
170 | i = -EFAULT; | ||
171 | } | ||
172 | return i; | ||
173 | } | ||