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/ia32/sys_ia32.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/ia32/sys_ia32.c')
-rw-r--r-- | arch/x86_64/ia32/sys_ia32.c | 1050 |
1 files changed, 1050 insertions, 0 deletions
diff --git a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c new file mode 100644 index 000000000000..68a9ab06ee7c --- /dev/null +++ b/arch/x86_64/ia32/sys_ia32.c | |||
@@ -0,0 +1,1050 @@ | |||
1 | /* | ||
2 | * sys_ia32.c: Conversion between 32bit and 64bit native syscalls. Based on | ||
3 | * sys_sparc32 | ||
4 | * | ||
5 | * Copyright (C) 2000 VA Linux Co | ||
6 | * Copyright (C) 2000 Don Dugger <n0ano@valinux.com> | ||
7 | * Copyright (C) 1999 Arun Sharma <arun.sharma@intel.com> | ||
8 | * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) | ||
9 | * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) | ||
10 | * Copyright (C) 2000 Hewlett-Packard Co. | ||
11 | * Copyright (C) 2000 David Mosberger-Tang <davidm@hpl.hp.com> | ||
12 | * Copyright (C) 2000,2001,2002 Andi Kleen, SuSE Labs (x86-64 port) | ||
13 | * | ||
14 | * These routines maintain argument size conversion between 32bit and 64bit | ||
15 | * environment. In 2.5 most of this should be moved to a generic directory. | ||
16 | * | ||
17 | * This file assumes that there is a hole at the end of user address space. | ||
18 | * | ||
19 | * Some of the functions are LE specific currently. These are hopefully all marked. | ||
20 | * This should be fixed. | ||
21 | */ | ||
22 | |||
23 | #include <linux/config.h> | ||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/sched.h> | ||
26 | #include <linux/fs.h> | ||
27 | #include <linux/file.h> | ||
28 | #include <linux/signal.h> | ||
29 | #include <linux/syscalls.h> | ||
30 | #include <linux/resource.h> | ||
31 | #include <linux/times.h> | ||
32 | #include <linux/utsname.h> | ||
33 | #include <linux/timex.h> | ||
34 | #include <linux/smp.h> | ||
35 | #include <linux/smp_lock.h> | ||
36 | #include <linux/sem.h> | ||
37 | #include <linux/msg.h> | ||
38 | #include <linux/mm.h> | ||
39 | #include <linux/shm.h> | ||
40 | #include <linux/slab.h> | ||
41 | #include <linux/uio.h> | ||
42 | #include <linux/nfs_fs.h> | ||
43 | #include <linux/quota.h> | ||
44 | #include <linux/module.h> | ||
45 | #include <linux/sunrpc/svc.h> | ||
46 | #include <linux/nfsd/nfsd.h> | ||
47 | #include <linux/nfsd/cache.h> | ||
48 | #include <linux/nfsd/xdr.h> | ||
49 | #include <linux/nfsd/syscall.h> | ||
50 | #include <linux/poll.h> | ||
51 | #include <linux/personality.h> | ||
52 | #include <linux/stat.h> | ||
53 | #include <linux/ipc.h> | ||
54 | #include <linux/rwsem.h> | ||
55 | #include <linux/binfmts.h> | ||
56 | #include <linux/init.h> | ||
57 | #include <linux/aio_abi.h> | ||
58 | #include <linux/aio.h> | ||
59 | #include <linux/compat.h> | ||
60 | #include <linux/vfs.h> | ||
61 | #include <linux/ptrace.h> | ||
62 | #include <linux/highuid.h> | ||
63 | #include <linux/vmalloc.h> | ||
64 | #include <asm/mman.h> | ||
65 | #include <asm/types.h> | ||
66 | #include <asm/uaccess.h> | ||
67 | #include <asm/semaphore.h> | ||
68 | #include <asm/atomic.h> | ||
69 | #include <asm/ldt.h> | ||
70 | |||
71 | #include <net/scm.h> | ||
72 | #include <net/sock.h> | ||
73 | #include <asm/ia32.h> | ||
74 | |||
75 | #define AA(__x) ((unsigned long)(__x)) | ||
76 | |||
77 | int cp_compat_stat(struct kstat *kbuf, struct compat_stat __user *ubuf) | ||
78 | { | ||
79 | typeof(ubuf->st_uid) uid = 0; | ||
80 | typeof(ubuf->st_gid) gid = 0; | ||
81 | SET_UID(uid, kbuf->uid); | ||
82 | SET_GID(gid, kbuf->gid); | ||
83 | if (!old_valid_dev(kbuf->dev) || !old_valid_dev(kbuf->rdev)) | ||
84 | return -EOVERFLOW; | ||
85 | if (kbuf->size >= 0x7fffffff) | ||
86 | return -EOVERFLOW; | ||
87 | if (!access_ok(VERIFY_WRITE, ubuf, sizeof(struct compat_stat)) || | ||
88 | __put_user (old_encode_dev(kbuf->dev), &ubuf->st_dev) || | ||
89 | __put_user (kbuf->ino, &ubuf->st_ino) || | ||
90 | __put_user (kbuf->mode, &ubuf->st_mode) || | ||
91 | __put_user (kbuf->nlink, &ubuf->st_nlink) || | ||
92 | __put_user (uid, &ubuf->st_uid) || | ||
93 | __put_user (gid, &ubuf->st_gid) || | ||
94 | __put_user (old_encode_dev(kbuf->rdev), &ubuf->st_rdev) || | ||
95 | __put_user (kbuf->size, &ubuf->st_size) || | ||
96 | __put_user (kbuf->atime.tv_sec, &ubuf->st_atime) || | ||
97 | __put_user (kbuf->atime.tv_nsec, &ubuf->st_atime_nsec) || | ||
98 | __put_user (kbuf->mtime.tv_sec, &ubuf->st_mtime) || | ||
99 | __put_user (kbuf->mtime.tv_nsec, &ubuf->st_mtime_nsec) || | ||
100 | __put_user (kbuf->ctime.tv_sec, &ubuf->st_ctime) || | ||
101 | __put_user (kbuf->ctime.tv_nsec, &ubuf->st_ctime_nsec) || | ||
102 | __put_user (kbuf->blksize, &ubuf->st_blksize) || | ||
103 | __put_user (kbuf->blocks, &ubuf->st_blocks)) | ||
104 | return -EFAULT; | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | asmlinkage long | ||
109 | sys32_truncate64(char __user * filename, unsigned long offset_low, unsigned long offset_high) | ||
110 | { | ||
111 | return sys_truncate(filename, ((loff_t) offset_high << 32) | offset_low); | ||
112 | } | ||
113 | |||
114 | asmlinkage long | ||
115 | sys32_ftruncate64(unsigned int fd, unsigned long offset_low, unsigned long offset_high) | ||
116 | { | ||
117 | return sys_ftruncate(fd, ((loff_t) offset_high << 32) | offset_low); | ||
118 | } | ||
119 | |||
120 | /* Another set for IA32/LFS -- x86_64 struct stat is different due to | ||
121 | support for 64bit inode numbers. */ | ||
122 | |||
123 | static int | ||
124 | cp_stat64(struct stat64 __user *ubuf, struct kstat *stat) | ||
125 | { | ||
126 | typeof(ubuf->st_uid) uid = 0; | ||
127 | typeof(ubuf->st_gid) gid = 0; | ||
128 | SET_UID(uid, stat->uid); | ||
129 | SET_GID(gid, stat->gid); | ||
130 | if (!access_ok(VERIFY_WRITE, ubuf, sizeof(struct stat64)) || | ||
131 | __put_user(huge_encode_dev(stat->dev), &ubuf->st_dev) || | ||
132 | __put_user (stat->ino, &ubuf->__st_ino) || | ||
133 | __put_user (stat->ino, &ubuf->st_ino) || | ||
134 | __put_user (stat->mode, &ubuf->st_mode) || | ||
135 | __put_user (stat->nlink, &ubuf->st_nlink) || | ||
136 | __put_user (uid, &ubuf->st_uid) || | ||
137 | __put_user (gid, &ubuf->st_gid) || | ||
138 | __put_user (huge_encode_dev(stat->rdev), &ubuf->st_rdev) || | ||
139 | __put_user (stat->size, &ubuf->st_size) || | ||
140 | __put_user (stat->atime.tv_sec, &ubuf->st_atime) || | ||
141 | __put_user (stat->atime.tv_nsec, &ubuf->st_atime_nsec) || | ||
142 | __put_user (stat->mtime.tv_sec, &ubuf->st_mtime) || | ||
143 | __put_user (stat->mtime.tv_nsec, &ubuf->st_mtime_nsec) || | ||
144 | __put_user (stat->ctime.tv_sec, &ubuf->st_ctime) || | ||
145 | __put_user (stat->ctime.tv_nsec, &ubuf->st_ctime_nsec) || | ||
146 | __put_user (stat->blksize, &ubuf->st_blksize) || | ||
147 | __put_user (stat->blocks, &ubuf->st_blocks)) | ||
148 | return -EFAULT; | ||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | asmlinkage long | ||
153 | sys32_stat64(char __user * filename, struct stat64 __user *statbuf) | ||
154 | { | ||
155 | struct kstat stat; | ||
156 | int ret = vfs_stat(filename, &stat); | ||
157 | if (!ret) | ||
158 | ret = cp_stat64(statbuf, &stat); | ||
159 | return ret; | ||
160 | } | ||
161 | |||
162 | asmlinkage long | ||
163 | sys32_lstat64(char __user * filename, struct stat64 __user *statbuf) | ||
164 | { | ||
165 | struct kstat stat; | ||
166 | int ret = vfs_lstat(filename, &stat); | ||
167 | if (!ret) | ||
168 | ret = cp_stat64(statbuf, &stat); | ||
169 | return ret; | ||
170 | } | ||
171 | |||
172 | asmlinkage long | ||
173 | sys32_fstat64(unsigned int fd, struct stat64 __user *statbuf) | ||
174 | { | ||
175 | struct kstat stat; | ||
176 | int ret = vfs_fstat(fd, &stat); | ||
177 | if (!ret) | ||
178 | ret = cp_stat64(statbuf, &stat); | ||
179 | return ret; | ||
180 | } | ||
181 | |||
182 | /* | ||
183 | * Linux/i386 didn't use to be able to handle more than | ||
184 | * 4 system call parameters, so these system calls used a memory | ||
185 | * block for parameter passing.. | ||
186 | */ | ||
187 | |||
188 | struct mmap_arg_struct { | ||
189 | unsigned int addr; | ||
190 | unsigned int len; | ||
191 | unsigned int prot; | ||
192 | unsigned int flags; | ||
193 | unsigned int fd; | ||
194 | unsigned int offset; | ||
195 | }; | ||
196 | |||
197 | asmlinkage long | ||
198 | sys32_mmap(struct mmap_arg_struct __user *arg) | ||
199 | { | ||
200 | struct mmap_arg_struct a; | ||
201 | struct file *file = NULL; | ||
202 | unsigned long retval; | ||
203 | struct mm_struct *mm ; | ||
204 | |||
205 | if (copy_from_user(&a, arg, sizeof(a))) | ||
206 | return -EFAULT; | ||
207 | |||
208 | if (a.offset & ~PAGE_MASK) | ||
209 | return -EINVAL; | ||
210 | |||
211 | if (!(a.flags & MAP_ANONYMOUS)) { | ||
212 | file = fget(a.fd); | ||
213 | if (!file) | ||
214 | return -EBADF; | ||
215 | } | ||
216 | |||
217 | mm = current->mm; | ||
218 | down_write(&mm->mmap_sem); | ||
219 | retval = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, a.offset>>PAGE_SHIFT); | ||
220 | if (file) | ||
221 | fput(file); | ||
222 | |||
223 | up_write(&mm->mmap_sem); | ||
224 | |||
225 | return retval; | ||
226 | } | ||
227 | |||
228 | asmlinkage long | ||
229 | sys32_mprotect(unsigned long start, size_t len, unsigned long prot) | ||
230 | { | ||
231 | return sys_mprotect(start,len,prot); | ||
232 | } | ||
233 | |||
234 | asmlinkage long | ||
235 | sys32_pipe(int __user *fd) | ||
236 | { | ||
237 | int retval; | ||
238 | int fds[2]; | ||
239 | |||
240 | retval = do_pipe(fds); | ||
241 | if (retval) | ||
242 | goto out; | ||
243 | if (copy_to_user(fd, fds, sizeof(fds))) | ||
244 | retval = -EFAULT; | ||
245 | out: | ||
246 | return retval; | ||
247 | } | ||
248 | |||
249 | asmlinkage long | ||
250 | sys32_rt_sigaction(int sig, struct sigaction32 __user *act, | ||
251 | struct sigaction32 __user *oact, unsigned int sigsetsize) | ||
252 | { | ||
253 | struct k_sigaction new_ka, old_ka; | ||
254 | int ret; | ||
255 | compat_sigset_t set32; | ||
256 | |||
257 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
258 | if (sigsetsize != sizeof(compat_sigset_t)) | ||
259 | return -EINVAL; | ||
260 | |||
261 | if (act) { | ||
262 | compat_uptr_t handler, restorer; | ||
263 | |||
264 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || | ||
265 | __get_user(handler, &act->sa_handler) || | ||
266 | __get_user(new_ka.sa.sa_flags, &act->sa_flags) || | ||
267 | __get_user(restorer, &act->sa_restorer)|| | ||
268 | __copy_from_user(&set32, &act->sa_mask, sizeof(compat_sigset_t))) | ||
269 | return -EFAULT; | ||
270 | new_ka.sa.sa_handler = compat_ptr(handler); | ||
271 | new_ka.sa.sa_restorer = compat_ptr(restorer); | ||
272 | /* FIXME: here we rely on _COMPAT_NSIG_WORS to be >= than _NSIG_WORDS << 1 */ | ||
273 | switch (_NSIG_WORDS) { | ||
274 | case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6] | ||
275 | | (((long)set32.sig[7]) << 32); | ||
276 | case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4] | ||
277 | | (((long)set32.sig[5]) << 32); | ||
278 | case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2] | ||
279 | | (((long)set32.sig[3]) << 32); | ||
280 | case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0] | ||
281 | | (((long)set32.sig[1]) << 32); | ||
282 | } | ||
283 | } | ||
284 | |||
285 | ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); | ||
286 | |||
287 | if (!ret && oact) { | ||
288 | /* FIXME: here we rely on _COMPAT_NSIG_WORS to be >= than _NSIG_WORDS << 1 */ | ||
289 | switch (_NSIG_WORDS) { | ||
290 | case 4: | ||
291 | set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32); | ||
292 | set32.sig[6] = old_ka.sa.sa_mask.sig[3]; | ||
293 | case 3: | ||
294 | set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32); | ||
295 | set32.sig[4] = old_ka.sa.sa_mask.sig[2]; | ||
296 | case 2: | ||
297 | set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32); | ||
298 | set32.sig[2] = old_ka.sa.sa_mask.sig[1]; | ||
299 | case 1: | ||
300 | set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32); | ||
301 | set32.sig[0] = old_ka.sa.sa_mask.sig[0]; | ||
302 | } | ||
303 | if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || | ||
304 | __put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler) || | ||
305 | __put_user(ptr_to_compat(old_ka.sa.sa_restorer), &oact->sa_restorer) || | ||
306 | __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || | ||
307 | __copy_to_user(&oact->sa_mask, &set32, sizeof(compat_sigset_t))) | ||
308 | return -EFAULT; | ||
309 | } | ||
310 | |||
311 | return ret; | ||
312 | } | ||
313 | |||
314 | asmlinkage long | ||
315 | sys32_sigaction (int sig, struct old_sigaction32 __user *act, struct old_sigaction32 __user *oact) | ||
316 | { | ||
317 | struct k_sigaction new_ka, old_ka; | ||
318 | int ret; | ||
319 | |||
320 | if (act) { | ||
321 | compat_old_sigset_t mask; | ||
322 | compat_uptr_t handler, restorer; | ||
323 | |||
324 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || | ||
325 | __get_user(handler, &act->sa_handler) || | ||
326 | __get_user(new_ka.sa.sa_flags, &act->sa_flags) || | ||
327 | __get_user(restorer, &act->sa_restorer) || | ||
328 | __get_user(mask, &act->sa_mask)) | ||
329 | return -EFAULT; | ||
330 | |||
331 | new_ka.sa.sa_handler = compat_ptr(handler); | ||
332 | new_ka.sa.sa_restorer = compat_ptr(restorer); | ||
333 | |||
334 | siginitset(&new_ka.sa.sa_mask, mask); | ||
335 | } | ||
336 | |||
337 | ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); | ||
338 | |||
339 | if (!ret && oact) { | ||
340 | if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || | ||
341 | __put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler) || | ||
342 | __put_user(ptr_to_compat(old_ka.sa.sa_restorer), &oact->sa_restorer) || | ||
343 | __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || | ||
344 | __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) | ||
345 | return -EFAULT; | ||
346 | } | ||
347 | |||
348 | return ret; | ||
349 | } | ||
350 | |||
351 | asmlinkage long | ||
352 | sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, | ||
353 | compat_sigset_t __user *oset, unsigned int sigsetsize) | ||
354 | { | ||
355 | sigset_t s; | ||
356 | compat_sigset_t s32; | ||
357 | int ret; | ||
358 | mm_segment_t old_fs = get_fs(); | ||
359 | |||
360 | if (set) { | ||
361 | if (copy_from_user (&s32, set, sizeof(compat_sigset_t))) | ||
362 | return -EFAULT; | ||
363 | switch (_NSIG_WORDS) { | ||
364 | case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32); | ||
365 | case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32); | ||
366 | case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32); | ||
367 | case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32); | ||
368 | } | ||
369 | } | ||
370 | set_fs (KERNEL_DS); | ||
371 | ret = sys_rt_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL, | ||
372 | sigsetsize); | ||
373 | set_fs (old_fs); | ||
374 | if (ret) return ret; | ||
375 | if (oset) { | ||
376 | switch (_NSIG_WORDS) { | ||
377 | case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3]; | ||
378 | case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2]; | ||
379 | case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1]; | ||
380 | case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0]; | ||
381 | } | ||
382 | if (copy_to_user (oset, &s32, sizeof(compat_sigset_t))) | ||
383 | return -EFAULT; | ||
384 | } | ||
385 | return 0; | ||
386 | } | ||
387 | |||
388 | static inline long | ||
389 | get_tv32(struct timeval *o, struct compat_timeval __user *i) | ||
390 | { | ||
391 | int err = -EFAULT; | ||
392 | if (access_ok(VERIFY_READ, i, sizeof(*i))) { | ||
393 | err = __get_user(o->tv_sec, &i->tv_sec); | ||
394 | err |= __get_user(o->tv_usec, &i->tv_usec); | ||
395 | } | ||
396 | return err; | ||
397 | } | ||
398 | |||
399 | static inline long | ||
400 | put_tv32(struct compat_timeval __user *o, struct timeval *i) | ||
401 | { | ||
402 | int err = -EFAULT; | ||
403 | if (access_ok(VERIFY_WRITE, o, sizeof(*o))) { | ||
404 | err = __put_user(i->tv_sec, &o->tv_sec); | ||
405 | err |= __put_user(i->tv_usec, &o->tv_usec); | ||
406 | } | ||
407 | return err; | ||
408 | } | ||
409 | |||
410 | extern int do_setitimer(int which, struct itimerval *, struct itimerval *); | ||
411 | |||
412 | asmlinkage long | ||
413 | sys32_alarm(unsigned int seconds) | ||
414 | { | ||
415 | struct itimerval it_new, it_old; | ||
416 | unsigned int oldalarm; | ||
417 | |||
418 | it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0; | ||
419 | it_new.it_value.tv_sec = seconds; | ||
420 | it_new.it_value.tv_usec = 0; | ||
421 | do_setitimer(ITIMER_REAL, &it_new, &it_old); | ||
422 | oldalarm = it_old.it_value.tv_sec; | ||
423 | /* ehhh.. We can't return 0 if we have an alarm pending.. */ | ||
424 | /* And we'd better return too much than too little anyway */ | ||
425 | if (it_old.it_value.tv_usec) | ||
426 | oldalarm++; | ||
427 | return oldalarm; | ||
428 | } | ||
429 | |||
430 | /* Translations due to time_t size differences. Which affects all | ||
431 | sorts of things, like timeval and itimerval. */ | ||
432 | |||
433 | extern struct timezone sys_tz; | ||
434 | |||
435 | asmlinkage long | ||
436 | sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz) | ||
437 | { | ||
438 | if (tv) { | ||
439 | struct timeval ktv; | ||
440 | do_gettimeofday(&ktv); | ||
441 | if (put_tv32(tv, &ktv)) | ||
442 | return -EFAULT; | ||
443 | } | ||
444 | if (tz) { | ||
445 | if (copy_to_user(tz, &sys_tz, sizeof(sys_tz))) | ||
446 | return -EFAULT; | ||
447 | } | ||
448 | return 0; | ||
449 | } | ||
450 | |||
451 | asmlinkage long | ||
452 | sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz) | ||
453 | { | ||
454 | struct timeval ktv; | ||
455 | struct timespec kts; | ||
456 | struct timezone ktz; | ||
457 | |||
458 | if (tv) { | ||
459 | if (get_tv32(&ktv, tv)) | ||
460 | return -EFAULT; | ||
461 | kts.tv_sec = ktv.tv_sec; | ||
462 | kts.tv_nsec = ktv.tv_usec * NSEC_PER_USEC; | ||
463 | } | ||
464 | if (tz) { | ||
465 | if (copy_from_user(&ktz, tz, sizeof(ktz))) | ||
466 | return -EFAULT; | ||
467 | } | ||
468 | |||
469 | return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL); | ||
470 | } | ||
471 | |||
472 | struct sel_arg_struct { | ||
473 | unsigned int n; | ||
474 | unsigned int inp; | ||
475 | unsigned int outp; | ||
476 | unsigned int exp; | ||
477 | unsigned int tvp; | ||
478 | }; | ||
479 | |||
480 | asmlinkage long | ||
481 | sys32_old_select(struct sel_arg_struct __user *arg) | ||
482 | { | ||
483 | struct sel_arg_struct a; | ||
484 | |||
485 | if (copy_from_user(&a, arg, sizeof(a))) | ||
486 | return -EFAULT; | ||
487 | return compat_sys_select(a.n, compat_ptr(a.inp), compat_ptr(a.outp), | ||
488 | compat_ptr(a.exp), compat_ptr(a.tvp)); | ||
489 | } | ||
490 | |||
491 | extern asmlinkage long | ||
492 | compat_sys_wait4(compat_pid_t pid, compat_uint_t * stat_addr, int options, | ||
493 | struct compat_rusage *ru); | ||
494 | |||
495 | asmlinkage long | ||
496 | sys32_waitpid(compat_pid_t pid, unsigned int *stat_addr, int options) | ||
497 | { | ||
498 | return compat_sys_wait4(pid, stat_addr, options, NULL); | ||
499 | } | ||
500 | |||
501 | int sys32_ni_syscall(int call) | ||
502 | { | ||
503 | struct task_struct *me = current; | ||
504 | static char lastcomm[sizeof(me->comm)]; | ||
505 | |||
506 | if (strncmp(lastcomm, me->comm, sizeof(lastcomm))) { | ||
507 | printk(KERN_INFO "IA32 syscall %d from %s not implemented\n", | ||
508 | call, me->comm); | ||
509 | strncpy(lastcomm, me->comm, sizeof(lastcomm)); | ||
510 | } | ||
511 | return -ENOSYS; | ||
512 | } | ||
513 | |||
514 | /* 32-bit timeval and related flotsam. */ | ||
515 | |||
516 | asmlinkage long | ||
517 | sys32_sysfs(int option, u32 arg1, u32 arg2) | ||
518 | { | ||
519 | return sys_sysfs(option, arg1, arg2); | ||
520 | } | ||
521 | |||
522 | struct sysinfo32 { | ||
523 | s32 uptime; | ||
524 | u32 loads[3]; | ||
525 | u32 totalram; | ||
526 | u32 freeram; | ||
527 | u32 sharedram; | ||
528 | u32 bufferram; | ||
529 | u32 totalswap; | ||
530 | u32 freeswap; | ||
531 | unsigned short procs; | ||
532 | unsigned short pad; | ||
533 | u32 totalhigh; | ||
534 | u32 freehigh; | ||
535 | u32 mem_unit; | ||
536 | char _f[20-2*sizeof(u32)-sizeof(int)]; | ||
537 | }; | ||
538 | |||
539 | asmlinkage long | ||
540 | sys32_sysinfo(struct sysinfo32 __user *info) | ||
541 | { | ||
542 | struct sysinfo s; | ||
543 | int ret; | ||
544 | mm_segment_t old_fs = get_fs (); | ||
545 | int bitcount = 0; | ||
546 | |||
547 | set_fs (KERNEL_DS); | ||
548 | ret = sys_sysinfo(&s); | ||
549 | set_fs (old_fs); | ||
550 | |||
551 | /* Check to see if any memory value is too large for 32-bit and scale | ||
552 | * down if needed | ||
553 | */ | ||
554 | if ((s.totalram >> 32) || (s.totalswap >> 32)) { | ||
555 | while (s.mem_unit < PAGE_SIZE) { | ||
556 | s.mem_unit <<= 1; | ||
557 | bitcount++; | ||
558 | } | ||
559 | s.totalram >>= bitcount; | ||
560 | s.freeram >>= bitcount; | ||
561 | s.sharedram >>= bitcount; | ||
562 | s.bufferram >>= bitcount; | ||
563 | s.totalswap >>= bitcount; | ||
564 | s.freeswap >>= bitcount; | ||
565 | s.totalhigh >>= bitcount; | ||
566 | s.freehigh >>= bitcount; | ||
567 | } | ||
568 | |||
569 | if (!access_ok(VERIFY_WRITE, info, sizeof(struct sysinfo32)) || | ||
570 | __put_user (s.uptime, &info->uptime) || | ||
571 | __put_user (s.loads[0], &info->loads[0]) || | ||
572 | __put_user (s.loads[1], &info->loads[1]) || | ||
573 | __put_user (s.loads[2], &info->loads[2]) || | ||
574 | __put_user (s.totalram, &info->totalram) || | ||
575 | __put_user (s.freeram, &info->freeram) || | ||
576 | __put_user (s.sharedram, &info->sharedram) || | ||
577 | __put_user (s.bufferram, &info->bufferram) || | ||
578 | __put_user (s.totalswap, &info->totalswap) || | ||
579 | __put_user (s.freeswap, &info->freeswap) || | ||
580 | __put_user (s.procs, &info->procs) || | ||
581 | __put_user (s.totalhigh, &info->totalhigh) || | ||
582 | __put_user (s.freehigh, &info->freehigh) || | ||
583 | __put_user (s.mem_unit, &info->mem_unit)) | ||
584 | return -EFAULT; | ||
585 | return 0; | ||
586 | } | ||
587 | |||
588 | asmlinkage long | ||
589 | sys32_sched_rr_get_interval(compat_pid_t pid, struct compat_timespec __user *interval) | ||
590 | { | ||
591 | struct timespec t; | ||
592 | int ret; | ||
593 | mm_segment_t old_fs = get_fs (); | ||
594 | |||
595 | set_fs (KERNEL_DS); | ||
596 | ret = sys_sched_rr_get_interval(pid, &t); | ||
597 | set_fs (old_fs); | ||
598 | if (put_compat_timespec(&t, interval)) | ||
599 | return -EFAULT; | ||
600 | return ret; | ||
601 | } | ||
602 | |||
603 | asmlinkage long | ||
604 | sys32_rt_sigpending(compat_sigset_t __user *set, compat_size_t sigsetsize) | ||
605 | { | ||
606 | sigset_t s; | ||
607 | compat_sigset_t s32; | ||
608 | int ret; | ||
609 | mm_segment_t old_fs = get_fs(); | ||
610 | |||
611 | set_fs (KERNEL_DS); | ||
612 | ret = sys_rt_sigpending(&s, sigsetsize); | ||
613 | set_fs (old_fs); | ||
614 | if (!ret) { | ||
615 | switch (_NSIG_WORDS) { | ||
616 | case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3]; | ||
617 | case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2]; | ||
618 | case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1]; | ||
619 | case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0]; | ||
620 | } | ||
621 | if (copy_to_user (set, &s32, sizeof(compat_sigset_t))) | ||
622 | return -EFAULT; | ||
623 | } | ||
624 | return ret; | ||
625 | } | ||
626 | |||
627 | asmlinkage long | ||
628 | sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo) | ||
629 | { | ||
630 | siginfo_t info; | ||
631 | int ret; | ||
632 | mm_segment_t old_fs = get_fs(); | ||
633 | |||
634 | if (copy_siginfo_from_user32(&info, uinfo)) | ||
635 | return -EFAULT; | ||
636 | set_fs (KERNEL_DS); | ||
637 | ret = sys_rt_sigqueueinfo(pid, sig, &info); | ||
638 | set_fs (old_fs); | ||
639 | return ret; | ||
640 | } | ||
641 | |||
642 | /* These are here just in case some old ia32 binary calls it. */ | ||
643 | asmlinkage long | ||
644 | sys32_pause(void) | ||
645 | { | ||
646 | current->state = TASK_INTERRUPTIBLE; | ||
647 | schedule(); | ||
648 | return -ERESTARTNOHAND; | ||
649 | } | ||
650 | |||
651 | |||
652 | #ifdef CONFIG_SYSCTL | ||
653 | struct sysctl_ia32 { | ||
654 | unsigned int name; | ||
655 | int nlen; | ||
656 | unsigned int oldval; | ||
657 | unsigned int oldlenp; | ||
658 | unsigned int newval; | ||
659 | unsigned int newlen; | ||
660 | unsigned int __unused[4]; | ||
661 | }; | ||
662 | |||
663 | |||
664 | asmlinkage long | ||
665 | sys32_sysctl(struct sysctl_ia32 __user *args32) | ||
666 | { | ||
667 | struct sysctl_ia32 a32; | ||
668 | mm_segment_t old_fs = get_fs (); | ||
669 | void __user *oldvalp, *newvalp; | ||
670 | size_t oldlen; | ||
671 | int __user *namep; | ||
672 | long ret; | ||
673 | extern int do_sysctl(int *name, int nlen, void *oldval, size_t *oldlenp, | ||
674 | void *newval, size_t newlen); | ||
675 | |||
676 | |||
677 | if (copy_from_user(&a32, args32, sizeof (a32))) | ||
678 | return -EFAULT; | ||
679 | |||
680 | /* | ||
681 | * We need to pre-validate these because we have to disable address checking | ||
682 | * before calling do_sysctl() because of OLDLEN but we can't run the risk of the | ||
683 | * user specifying bad addresses here. Well, since we're dealing with 32 bit | ||
684 | * addresses, we KNOW that access_ok() will always succeed, so this is an | ||
685 | * expensive NOP, but so what... | ||
686 | */ | ||
687 | namep = compat_ptr(a32.name); | ||
688 | oldvalp = compat_ptr(a32.oldval); | ||
689 | newvalp = compat_ptr(a32.newval); | ||
690 | |||
691 | if ((oldvalp && get_user(oldlen, (int __user *)compat_ptr(a32.oldlenp))) | ||
692 | || !access_ok(VERIFY_WRITE, namep, 0) | ||
693 | || !access_ok(VERIFY_WRITE, oldvalp, 0) | ||
694 | || !access_ok(VERIFY_WRITE, newvalp, 0)) | ||
695 | return -EFAULT; | ||
696 | |||
697 | set_fs(KERNEL_DS); | ||
698 | lock_kernel(); | ||
699 | ret = do_sysctl(namep, a32.nlen, oldvalp, &oldlen, newvalp, (size_t) a32.newlen); | ||
700 | unlock_kernel(); | ||
701 | set_fs(old_fs); | ||
702 | |||
703 | if (oldvalp && put_user (oldlen, (int __user *)compat_ptr(a32.oldlenp))) | ||
704 | return -EFAULT; | ||
705 | |||
706 | return ret; | ||
707 | } | ||
708 | #endif | ||
709 | |||
710 | /* warning: next two assume little endian */ | ||
711 | asmlinkage long | ||
712 | sys32_pread(unsigned int fd, char __user *ubuf, u32 count, u32 poslo, u32 poshi) | ||
713 | { | ||
714 | return sys_pread64(fd, ubuf, count, | ||
715 | ((loff_t)AA(poshi) << 32) | AA(poslo)); | ||
716 | } | ||
717 | |||
718 | asmlinkage long | ||
719 | sys32_pwrite(unsigned int fd, char __user *ubuf, u32 count, u32 poslo, u32 poshi) | ||
720 | { | ||
721 | return sys_pwrite64(fd, ubuf, count, | ||
722 | ((loff_t)AA(poshi) << 32) | AA(poslo)); | ||
723 | } | ||
724 | |||
725 | |||
726 | asmlinkage long | ||
727 | sys32_personality(unsigned long personality) | ||
728 | { | ||
729 | int ret; | ||
730 | if (personality(current->personality) == PER_LINUX32 && | ||
731 | personality == PER_LINUX) | ||
732 | personality = PER_LINUX32; | ||
733 | ret = sys_personality(personality); | ||
734 | if (ret == PER_LINUX32) | ||
735 | ret = PER_LINUX; | ||
736 | return ret; | ||
737 | } | ||
738 | |||
739 | asmlinkage long | ||
740 | sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, s32 count) | ||
741 | { | ||
742 | mm_segment_t old_fs = get_fs(); | ||
743 | int ret; | ||
744 | off_t of; | ||
745 | |||
746 | if (offset && get_user(of, offset)) | ||
747 | return -EFAULT; | ||
748 | |||
749 | set_fs(KERNEL_DS); | ||
750 | ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count); | ||
751 | set_fs(old_fs); | ||
752 | |||
753 | if (!ret && offset && put_user(of, offset)) | ||
754 | return -EFAULT; | ||
755 | |||
756 | return ret; | ||
757 | } | ||
758 | |||
759 | /* Handle adjtimex compatibility. */ | ||
760 | |||
761 | struct timex32 { | ||
762 | u32 modes; | ||
763 | s32 offset, freq, maxerror, esterror; | ||
764 | s32 status, constant, precision, tolerance; | ||
765 | struct compat_timeval time; | ||
766 | s32 tick; | ||
767 | s32 ppsfreq, jitter, shift, stabil; | ||
768 | s32 jitcnt, calcnt, errcnt, stbcnt; | ||
769 | s32 :32; s32 :32; s32 :32; s32 :32; | ||
770 | s32 :32; s32 :32; s32 :32; s32 :32; | ||
771 | s32 :32; s32 :32; s32 :32; s32 :32; | ||
772 | }; | ||
773 | |||
774 | extern int do_adjtimex(struct timex *); | ||
775 | |||
776 | asmlinkage long | ||
777 | sys32_adjtimex(struct timex32 __user *utp) | ||
778 | { | ||
779 | struct timex txc; | ||
780 | int ret; | ||
781 | |||
782 | memset(&txc, 0, sizeof(struct timex)); | ||
783 | |||
784 | if (!access_ok(VERIFY_READ, utp, sizeof(struct timex32)) || | ||
785 | __get_user(txc.modes, &utp->modes) || | ||
786 | __get_user(txc.offset, &utp->offset) || | ||
787 | __get_user(txc.freq, &utp->freq) || | ||
788 | __get_user(txc.maxerror, &utp->maxerror) || | ||
789 | __get_user(txc.esterror, &utp->esterror) || | ||
790 | __get_user(txc.status, &utp->status) || | ||
791 | __get_user(txc.constant, &utp->constant) || | ||
792 | __get_user(txc.precision, &utp->precision) || | ||
793 | __get_user(txc.tolerance, &utp->tolerance) || | ||
794 | __get_user(txc.time.tv_sec, &utp->time.tv_sec) || | ||
795 | __get_user(txc.time.tv_usec, &utp->time.tv_usec) || | ||
796 | __get_user(txc.tick, &utp->tick) || | ||
797 | __get_user(txc.ppsfreq, &utp->ppsfreq) || | ||
798 | __get_user(txc.jitter, &utp->jitter) || | ||
799 | __get_user(txc.shift, &utp->shift) || | ||
800 | __get_user(txc.stabil, &utp->stabil) || | ||
801 | __get_user(txc.jitcnt, &utp->jitcnt) || | ||
802 | __get_user(txc.calcnt, &utp->calcnt) || | ||
803 | __get_user(txc.errcnt, &utp->errcnt) || | ||
804 | __get_user(txc.stbcnt, &utp->stbcnt)) | ||
805 | return -EFAULT; | ||
806 | |||
807 | ret = do_adjtimex(&txc); | ||
808 | |||
809 | if (!access_ok(VERIFY_WRITE, utp, sizeof(struct timex32)) || | ||
810 | __put_user(txc.modes, &utp->modes) || | ||
811 | __put_user(txc.offset, &utp->offset) || | ||
812 | __put_user(txc.freq, &utp->freq) || | ||
813 | __put_user(txc.maxerror, &utp->maxerror) || | ||
814 | __put_user(txc.esterror, &utp->esterror) || | ||
815 | __put_user(txc.status, &utp->status) || | ||
816 | __put_user(txc.constant, &utp->constant) || | ||
817 | __put_user(txc.precision, &utp->precision) || | ||
818 | __put_user(txc.tolerance, &utp->tolerance) || | ||
819 | __put_user(txc.time.tv_sec, &utp->time.tv_sec) || | ||
820 | __put_user(txc.time.tv_usec, &utp->time.tv_usec) || | ||
821 | __put_user(txc.tick, &utp->tick) || | ||
822 | __put_user(txc.ppsfreq, &utp->ppsfreq) || | ||
823 | __put_user(txc.jitter, &utp->jitter) || | ||
824 | __put_user(txc.shift, &utp->shift) || | ||
825 | __put_user(txc.stabil, &utp->stabil) || | ||
826 | __put_user(txc.jitcnt, &utp->jitcnt) || | ||
827 | __put_user(txc.calcnt, &utp->calcnt) || | ||
828 | __put_user(txc.errcnt, &utp->errcnt) || | ||
829 | __put_user(txc.stbcnt, &utp->stbcnt)) | ||
830 | ret = -EFAULT; | ||
831 | |||
832 | return ret; | ||
833 | } | ||
834 | |||
835 | asmlinkage long sys32_mmap2(unsigned long addr, unsigned long len, | ||
836 | unsigned long prot, unsigned long flags, | ||
837 | unsigned long fd, unsigned long pgoff) | ||
838 | { | ||
839 | struct mm_struct *mm = current->mm; | ||
840 | unsigned long error; | ||
841 | struct file * file = NULL; | ||
842 | |||
843 | flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); | ||
844 | if (!(flags & MAP_ANONYMOUS)) { | ||
845 | file = fget(fd); | ||
846 | if (!file) | ||
847 | return -EBADF; | ||
848 | } | ||
849 | |||
850 | down_write(&mm->mmap_sem); | ||
851 | error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); | ||
852 | up_write(&mm->mmap_sem); | ||
853 | |||
854 | if (file) | ||
855 | fput(file); | ||
856 | return error; | ||
857 | } | ||
858 | |||
859 | asmlinkage long sys32_olduname(struct oldold_utsname __user * name) | ||
860 | { | ||
861 | int error; | ||
862 | |||
863 | if (!name) | ||
864 | return -EFAULT; | ||
865 | if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname))) | ||
866 | return -EFAULT; | ||
867 | |||
868 | down_read(&uts_sem); | ||
869 | |||
870 | error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN); | ||
871 | __put_user(0,name->sysname+__OLD_UTS_LEN); | ||
872 | __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN); | ||
873 | __put_user(0,name->nodename+__OLD_UTS_LEN); | ||
874 | __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN); | ||
875 | __put_user(0,name->release+__OLD_UTS_LEN); | ||
876 | __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN); | ||
877 | __put_user(0,name->version+__OLD_UTS_LEN); | ||
878 | { | ||
879 | char *arch = "x86_64"; | ||
880 | if (personality(current->personality) == PER_LINUX32) | ||
881 | arch = "i686"; | ||
882 | |||
883 | __copy_to_user(&name->machine,arch,strlen(arch)+1); | ||
884 | } | ||
885 | |||
886 | up_read(&uts_sem); | ||
887 | |||
888 | error = error ? -EFAULT : 0; | ||
889 | |||
890 | return error; | ||
891 | } | ||
892 | |||
893 | long sys32_uname(struct old_utsname __user * name) | ||
894 | { | ||
895 | int err; | ||
896 | if (!name) | ||
897 | return -EFAULT; | ||
898 | down_read(&uts_sem); | ||
899 | err=copy_to_user(name, &system_utsname, sizeof (*name)); | ||
900 | up_read(&uts_sem); | ||
901 | if (personality(current->personality) == PER_LINUX32) | ||
902 | err |= copy_to_user(&name->machine, "i686", 5); | ||
903 | return err?-EFAULT:0; | ||
904 | } | ||
905 | |||
906 | long sys32_ustat(unsigned dev, struct ustat32 __user *u32p) | ||
907 | { | ||
908 | struct ustat u; | ||
909 | mm_segment_t seg; | ||
910 | int ret; | ||
911 | |||
912 | seg = get_fs(); | ||
913 | set_fs(KERNEL_DS); | ||
914 | ret = sys_ustat(dev,&u); | ||
915 | set_fs(seg); | ||
916 | if (ret >= 0) { | ||
917 | if (!access_ok(VERIFY_WRITE,u32p,sizeof(struct ustat32)) || | ||
918 | __put_user((__u32) u.f_tfree, &u32p->f_tfree) || | ||
919 | __put_user((__u32) u.f_tinode, &u32p->f_tfree) || | ||
920 | __copy_to_user(&u32p->f_fname, u.f_fname, sizeof(u.f_fname)) || | ||
921 | __copy_to_user(&u32p->f_fpack, u.f_fpack, sizeof(u.f_fpack))) | ||
922 | ret = -EFAULT; | ||
923 | } | ||
924 | return ret; | ||
925 | } | ||
926 | |||
927 | asmlinkage long sys32_execve(char __user *name, compat_uptr_t __user *argv, | ||
928 | compat_uptr_t __user *envp, struct pt_regs *regs) | ||
929 | { | ||
930 | long error; | ||
931 | char * filename; | ||
932 | |||
933 | filename = getname(name); | ||
934 | error = PTR_ERR(filename); | ||
935 | if (IS_ERR(filename)) | ||
936 | return error; | ||
937 | error = compat_do_execve(filename, argv, envp, regs); | ||
938 | if (error == 0) { | ||
939 | task_lock(current); | ||
940 | current->ptrace &= ~PT_DTRACE; | ||
941 | task_unlock(current); | ||
942 | } | ||
943 | putname(filename); | ||
944 | return error; | ||
945 | } | ||
946 | |||
947 | asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp, | ||
948 | struct pt_regs *regs) | ||
949 | { | ||
950 | void __user *parent_tid = (void __user *)regs->rdx; | ||
951 | void __user *child_tid = (void __user *)regs->rdi; | ||
952 | if (!newsp) | ||
953 | newsp = regs->rsp; | ||
954 | return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid); | ||
955 | } | ||
956 | |||
957 | /* | ||
958 | * Some system calls that need sign extended arguments. This could be done by a generic wrapper. | ||
959 | */ | ||
960 | |||
961 | long sys32_lseek (unsigned int fd, int offset, unsigned int whence) | ||
962 | { | ||
963 | return sys_lseek(fd, offset, whence); | ||
964 | } | ||
965 | |||
966 | long sys32_kill(int pid, int sig) | ||
967 | { | ||
968 | return sys_kill(pid, sig); | ||
969 | } | ||
970 | |||
971 | asmlinkage long sys32_open(const char __user * filename, int flags, int mode) | ||
972 | { | ||
973 | char * tmp; | ||
974 | int fd, error; | ||
975 | |||
976 | /* don't force O_LARGEFILE */ | ||
977 | tmp = getname(filename); | ||
978 | fd = PTR_ERR(tmp); | ||
979 | if (!IS_ERR(tmp)) { | ||
980 | fd = get_unused_fd(); | ||
981 | if (fd >= 0) { | ||
982 | struct file *f = filp_open(tmp, flags, mode); | ||
983 | error = PTR_ERR(f); | ||
984 | if (IS_ERR(f)) { | ||
985 | put_unused_fd(fd); | ||
986 | fd = error; | ||
987 | } else | ||
988 | fd_install(fd, f); | ||
989 | } | ||
990 | putname(tmp); | ||
991 | } | ||
992 | return fd; | ||
993 | } | ||
994 | |||
995 | extern asmlinkage long | ||
996 | sys_timer_create(clockid_t which_clock, | ||
997 | struct sigevent __user *timer_event_spec, | ||
998 | timer_t __user * created_timer_id); | ||
999 | |||
1000 | long | ||
1001 | sys32_timer_create(u32 clock, struct compat_sigevent __user *se32, timer_t __user *timer_id) | ||
1002 | { | ||
1003 | struct sigevent __user *p = NULL; | ||
1004 | if (se32) { | ||
1005 | struct sigevent se; | ||
1006 | p = compat_alloc_user_space(sizeof(struct sigevent)); | ||
1007 | if (get_compat_sigevent(&se, se32) || | ||
1008 | copy_to_user(p, &se, sizeof(se))) | ||
1009 | return -EFAULT; | ||
1010 | } | ||
1011 | return sys_timer_create(clock, p, timer_id); | ||
1012 | } | ||
1013 | |||
1014 | long sys32_fadvise64_64(int fd, __u32 offset_low, __u32 offset_high, | ||
1015 | __u32 len_low, __u32 len_high, int advice) | ||
1016 | { | ||
1017 | return sys_fadvise64_64(fd, | ||
1018 | (((u64)offset_high)<<32) | offset_low, | ||
1019 | (((u64)len_high)<<32) | len_low, | ||
1020 | advice); | ||
1021 | } | ||
1022 | |||
1023 | long sys32_vm86_warning(void) | ||
1024 | { | ||
1025 | struct task_struct *me = current; | ||
1026 | static char lastcomm[sizeof(me->comm)]; | ||
1027 | if (strncmp(lastcomm, me->comm, sizeof(lastcomm))) { | ||
1028 | printk(KERN_INFO "%s: vm86 mode not supported on 64 bit kernel\n", | ||
1029 | me->comm); | ||
1030 | strncpy(lastcomm, me->comm, sizeof(lastcomm)); | ||
1031 | } | ||
1032 | return -ENOSYS; | ||
1033 | } | ||
1034 | |||
1035 | long sys32_lookup_dcookie(u32 addr_low, u32 addr_high, | ||
1036 | char __user * buf, size_t len) | ||
1037 | { | ||
1038 | return sys_lookup_dcookie(((u64)addr_high << 32) | addr_low, buf, len); | ||
1039 | } | ||
1040 | |||
1041 | static int __init ia32_init (void) | ||
1042 | { | ||
1043 | printk("IA32 emulation $Id: sys_ia32.c,v 1.32 2002/03/24 13:02:28 ak Exp $\n"); | ||
1044 | return 0; | ||
1045 | } | ||
1046 | |||
1047 | __initcall(ia32_init); | ||
1048 | |||
1049 | extern unsigned long ia32_sys_call_table[]; | ||
1050 | EXPORT_SYMBOL(ia32_sys_call_table); | ||