39d1e95bc69291c65fa8d8095c7be7077d71fd14
[linux-flexiantxendom0-3.2.10.git] / arch / ia64 / ia32 / sys_ia32.c
1 /*
2  * sys_ia32.c: Conversion between 32bit and 64bit native syscalls. Derived from sys_sparc32.c.
3  *
4  * Copyright (C) 2000           VA Linux Co
5  * Copyright (C) 2000           Don Dugger <n0ano@valinux.com>
6  * Copyright (C) 1999           Arun Sharma <arun.sharma@intel.com>
7  * Copyright (C) 1997,1998      Jakub Jelinek (jj@sunsite.mff.cuni.cz)
8  * Copyright (C) 1997           David S. Miller (davem@caip.rutgers.edu)
9  * Copyright (C) 2000-2003 Hewlett-Packard Co
10  *      David Mosberger-Tang <davidm@hpl.hp.com>
11  *
12  * These routines maintain argument size conversion between 32bit and 64bit
13  * environment.
14  */
15
16 #include <linux/config.h>
17 #include <linux/kernel.h>
18 #include <linux/sysctl.h>
19 #include <linux/sched.h>
20 #include <linux/fs.h>
21 #include <linux/file.h>
22 #include <linux/signal.h>
23 #include <linux/resource.h>
24 #include <linux/times.h>
25 #include <linux/utsname.h>
26 #include <linux/timex.h>
27 #include <linux/smp.h>
28 #include <linux/smp_lock.h>
29 #include <linux/sem.h>
30 #include <linux/msg.h>
31 #include <linux/mm.h>
32 #include <linux/shm.h>
33 #include <linux/slab.h>
34 #include <linux/uio.h>
35 #include <linux/nfs_fs.h>
36 #include <linux/smb_fs.h>
37 #include <linux/smb_mount.h>
38 #include <linux/ncp_fs.h>
39 #include <linux/quota.h>
40 #include <linux/sunrpc/svc.h>
41 #include <linux/nfsd/nfsd.h>
42 #include <linux/nfsd/cache.h>
43 #include <linux/nfsd/xdr.h>
44 #include <linux/nfsd/syscall.h>
45 #include <linux/poll.h>
46 #include <linux/eventpoll.h>
47 #include <linux/personality.h>
48 #include <linux/ptrace.h>
49 #include <linux/stat.h>
50 #include <linux/ipc.h>
51 #include <linux/compat.h>
52 #include <linux/vfs.h>
53
54 #include <asm/intrinsics.h>
55 #include <asm/semaphore.h>
56 #include <asm/types.h>
57 #include <asm/uaccess.h>
58
59 #include "ia32priv.h"
60
61 #include <net/scm.h>
62 #include <net/sock.h>
63
64 #define DEBUG   0
65
66 #if DEBUG
67 # define DBG(fmt...)    printk(KERN_DEBUG fmt)
68 #else
69 # define DBG(fmt...)
70 #endif
71
72 #define A(__x)          ((unsigned long)(__x))
73 #define AA(__x)         ((unsigned long)(__x))
74 #define ROUND_UP(x,a)   ((__typeof__(x))(((unsigned long)(x) + ((a) - 1)) & ~((a) - 1)))
75 #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
76
77 #define OFFSET4K(a)             ((a) & 0xfff)
78 #define PAGE_START(addr)        ((addr) & PAGE_MASK)
79 #define MINSIGSTKSZ_IA32        2048
80
81 #define high2lowuid(uid) ((uid) > 65535 ? 65534 : (uid))
82 #define high2lowgid(gid) ((gid) > 65535 ? 65534 : (gid))
83
84 extern asmlinkage long sys_execve (char *, char **, char **, struct pt_regs *);
85 extern asmlinkage long sys_mprotect (unsigned long, size_t, unsigned long);
86 extern asmlinkage long sys_munmap (unsigned long, size_t);
87 extern unsigned long arch_get_unmapped_area (struct file *, unsigned long, unsigned long,
88                                              unsigned long, unsigned long);
89
90 /* forward declaration: */
91 asmlinkage long sys32_mprotect (unsigned int, unsigned int, int);
92 asmlinkage unsigned long sys_brk(unsigned long);
93
94 /*
95  * Anything that modifies or inspects ia32 user virtual memory must hold this semaphore
96  * while doing so.
97  */
98 /* XXX make per-mm: */
99 static DECLARE_MUTEX(ia32_mmap_sem);
100
101 static int
102 nargs (unsigned int arg, char **ap)
103 {
104         unsigned int addr;
105         int n, err;
106
107         if (!arg)
108                 return 0;
109
110         n = 0;
111         do {
112                 err = get_user(addr, (unsigned int *)A(arg));
113                 if (err)
114                         return err;
115                 if (ap)
116                         *ap++ = (char *) A(addr);
117                 arg += sizeof(unsigned int);
118                 n++;
119         } while (addr);
120         return n - 1;
121 }
122
123 asmlinkage long
124 sys32_execve (char *filename, unsigned int argv, unsigned int envp,
125               struct pt_regs *regs)
126 {
127         unsigned long old_map_base, old_task_size, tssd;
128         char **av, **ae;
129         int na, ne, len;
130         long r;
131
132         na = nargs(argv, NULL);
133         if (na < 0)
134                 return na;
135         ne = nargs(envp, NULL);
136         if (ne < 0)
137                 return ne;
138         len = (na + ne + 2) * sizeof(*av);
139         av = kmalloc(len, GFP_KERNEL);
140         if (!av)
141                 return -ENOMEM;
142
143         ae = av + na + 1;
144         av[na] = NULL;
145         ae[ne] = NULL;
146
147         r = nargs(argv, av);
148         if (r < 0)
149                 goto out;
150         r = nargs(envp, ae);
151         if (r < 0)
152                 goto out;
153
154         old_map_base  = current->thread.map_base;
155         old_task_size = current->thread.task_size;
156         tssd = ia64_get_kr(IA64_KR_TSSD);
157
158         /* we may be exec'ing a 64-bit process: reset map base, task-size, and io-base: */
159         current->thread.map_base  = DEFAULT_MAP_BASE;
160         current->thread.task_size = DEFAULT_TASK_SIZE;
161         ia64_set_kr(IA64_KR_IO_BASE, current->thread.old_iob);
162         ia64_set_kr(IA64_KR_TSSD, current->thread.old_k1);
163
164         set_fs(KERNEL_DS);
165         r = sys_execve(filename, av, ae, regs);
166         if (r < 0) {
167                 /* oops, execve failed, switch back to old values... */
168                 ia64_set_kr(IA64_KR_IO_BASE, IA32_IOBASE);
169                 ia64_set_kr(IA64_KR_TSSD, tssd);
170                 current->thread.map_base  = old_map_base;
171                 current->thread.task_size = old_task_size;
172                 set_fs(USER_DS);        /* establish new task-size as the address-limit */
173         }
174   out:
175         kfree(av);
176         return r;
177 }
178
179 int cp_compat_stat(struct kstat *stat, struct compat_stat *ubuf)
180 {
181         int err;
182
183         if ((u64) stat->size > MAX_NON_LFS ||
184             !old_valid_dev(stat->dev) ||
185             !old_valid_dev(stat->rdev))
186                 return -EOVERFLOW;
187
188         if (clear_user(ubuf, sizeof(*ubuf)))
189                 return -EFAULT;
190
191         err  = __put_user(old_encode_dev(stat->dev), &ubuf->st_dev);
192         err |= __put_user(stat->ino, &ubuf->st_ino);
193         err |= __put_user(stat->mode, &ubuf->st_mode);
194         err |= __put_user(stat->nlink, &ubuf->st_nlink);
195         err |= __put_user(high2lowuid(stat->uid), &ubuf->st_uid);
196         err |= __put_user(high2lowgid(stat->gid), &ubuf->st_gid);
197         err |= __put_user(old_encode_dev(stat->rdev), &ubuf->st_rdev);
198         err |= __put_user(stat->size, &ubuf->st_size);
199         err |= __put_user(stat->atime.tv_sec, &ubuf->st_atime);
200         err |= __put_user(stat->atime.tv_nsec, &ubuf->st_atime_nsec);
201         err |= __put_user(stat->mtime.tv_sec, &ubuf->st_mtime);
202         err |= __put_user(stat->mtime.tv_nsec, &ubuf->st_mtime_nsec);
203         err |= __put_user(stat->ctime.tv_sec, &ubuf->st_ctime);
204         err |= __put_user(stat->ctime.tv_nsec, &ubuf->st_ctime_nsec);
205         err |= __put_user(stat->blksize, &ubuf->st_blksize);
206         err |= __put_user(stat->blocks, &ubuf->st_blocks);
207         return err;
208 }
209
210 #if PAGE_SHIFT > IA32_PAGE_SHIFT
211
212
213 static int
214 get_page_prot (struct vm_area_struct *vma, unsigned long addr)
215 {
216         int prot = 0;
217
218         if (!vma || vma->vm_start > addr)
219                 return 0;
220
221         if (vma->vm_flags & VM_READ)
222                 prot |= PROT_READ;
223         if (vma->vm_flags & VM_WRITE)
224                 prot |= PROT_WRITE;
225         if (vma->vm_flags & VM_EXEC)
226                 prot |= PROT_EXEC;
227         return prot;
228 }
229
230 /*
231  * Map a subpage by creating an anonymous page that contains the union of the old page and
232  * the subpage.
233  */
234 static unsigned long
235 mmap_subpage (struct file *file, unsigned long start, unsigned long end, int prot, int flags,
236               loff_t off)
237 {
238         void *page = NULL;
239         struct inode *inode;
240         unsigned long ret = 0;
241         struct vm_area_struct *vma = find_vma(current->mm, start);
242         int old_prot = get_page_prot(vma, start);
243
244         DBG("mmap_subpage(file=%p,start=0x%lx,end=0x%lx,prot=%x,flags=%x,off=0x%llx)\n",
245             file, start, end, prot, flags, off);
246
247
248         /* Optimize the case where the old mmap and the new mmap are both anonymous */
249         if ((old_prot & PROT_WRITE) && (flags & MAP_ANONYMOUS) && !vma->vm_file) {
250                 if (clear_user((void *) start, end - start)) {
251                         ret = -EFAULT;
252                         goto out;
253                 }
254                 goto skip_mmap;
255         }
256
257         page = (void *) get_zeroed_page(GFP_KERNEL);
258         if (!page)
259                 return -ENOMEM;
260
261         if (old_prot)
262                 copy_from_user(page, (void *) PAGE_START(start), PAGE_SIZE);
263
264         down_write(&current->mm->mmap_sem);
265         {
266                 ret = do_mmap(0, PAGE_START(start), PAGE_SIZE, prot | PROT_WRITE,
267                               flags | MAP_FIXED | MAP_ANONYMOUS, 0);
268         }
269         up_write(&current->mm->mmap_sem);
270
271         if (IS_ERR((void *) ret))
272                 goto out;
273
274         if (old_prot) {
275                 /* copy back the old page contents.  */
276                 if (offset_in_page(start))
277                         copy_to_user((void *) PAGE_START(start), page, offset_in_page(start));
278                 if (offset_in_page(end))
279                         copy_to_user((void *) end, page + offset_in_page(end),
280                                      PAGE_SIZE - offset_in_page(end));
281         }
282
283         if (!(flags & MAP_ANONYMOUS)) {
284                 /* read the file contents */
285                 inode = file->f_dentry->d_inode;
286                 if (!inode->i_fop || !file->f_op->read
287                     || ((*file->f_op->read)(file, (char *) start, end - start, &off) < 0))
288                 {
289                         ret = -EINVAL;
290                         goto out;
291                 }
292         }
293
294  skip_mmap:
295         if (!(prot & PROT_WRITE))
296                 ret = sys_mprotect(PAGE_START(start), PAGE_SIZE, prot | old_prot);
297   out:
298         if (page)
299                 free_page((unsigned long) page);
300         return ret;
301 }
302
303 static unsigned long
304 emulate_mmap (struct file *file, unsigned long start, unsigned long len, int prot, int flags,
305               loff_t off)
306 {
307         unsigned long tmp, end, pend, pstart, ret, is_congruent, fudge = 0;
308         struct inode *inode;
309         loff_t poff;
310
311         end = start + len;
312         pstart = PAGE_START(start);
313         pend = PAGE_ALIGN(end);
314
315         if (flags & MAP_FIXED) {
316                 if (start > pstart) {
317                         if (flags & MAP_SHARED)
318                                 printk(KERN_INFO
319                                        "%s(%d): emulate_mmap() can't share head (addr=0x%lx)\n",
320                                        current->comm, current->pid, start);
321                         ret = mmap_subpage(file, start, min(PAGE_ALIGN(start), end), prot, flags,
322                                            off);
323                         if (IS_ERR((void *) ret))
324                                 return ret;
325                         pstart += PAGE_SIZE;
326                         if (pstart >= pend)
327                                 return start;   /* done */
328                 }
329                 if (end < pend) {
330                         if (flags & MAP_SHARED)
331                                 printk(KERN_INFO
332                                        "%s(%d): emulate_mmap() can't share tail (end=0x%lx)\n",
333                                        current->comm, current->pid, end);
334                         ret = mmap_subpage(file, max(start, PAGE_START(end)), end, prot, flags,
335                                            (off + len) - offset_in_page(end));
336                         if (IS_ERR((void *) ret))
337                                 return ret;
338                         pend -= PAGE_SIZE;
339                         if (pstart >= pend)
340                                 return start;   /* done */
341                 }
342         } else {
343                 /*
344                  * If a start address was specified, use it if the entire rounded out area
345                  * is available.
346                  */
347                 if (start && !pstart)
348                         fudge = 1;      /* handle case of mapping to range (0,PAGE_SIZE) */
349                 tmp = arch_get_unmapped_area(file, pstart - fudge, pend - pstart, 0, flags);
350                 if (tmp != pstart) {
351                         pstart = tmp;
352                         start = pstart + offset_in_page(off);   /* make start congruent with off */
353                         end = start + len;
354                         pend = PAGE_ALIGN(end);
355                 }
356         }
357
358         poff = off + (pstart - start);  /* note: (pstart - start) may be negative */
359         is_congruent = (flags & MAP_ANONYMOUS) || (offset_in_page(poff) == 0);
360
361         if ((flags & MAP_SHARED) && !is_congruent)
362                 printk(KERN_INFO "%s(%d): emulate_mmap() can't share contents of incongruent mmap "
363                        "(addr=0x%lx,off=0x%llx)\n", current->comm, current->pid, start, off);
364
365         DBG("mmap_body: mapping [0x%lx-0x%lx) %s with poff 0x%llx\n", pstart, pend,
366             is_congruent ? "congruent" : "not congruent", poff);
367
368         down_write(&current->mm->mmap_sem);
369         {
370                 if (!(flags & MAP_ANONYMOUS) && is_congruent)
371                         ret = do_mmap(file, pstart, pend - pstart, prot, flags | MAP_FIXED, poff);
372                 else
373                         ret = do_mmap(0, pstart, pend - pstart,
374                                       prot | ((flags & MAP_ANONYMOUS) ? 0 : PROT_WRITE),
375                                       flags | MAP_FIXED | MAP_ANONYMOUS, 0);
376         }
377         up_write(&current->mm->mmap_sem);
378
379         if (IS_ERR((void *) ret))
380                 return ret;
381
382         if (!is_congruent) {
383                 /* read the file contents */
384                 inode = file->f_dentry->d_inode;
385                 if (!inode->i_fop || !file->f_op->read
386                     || ((*file->f_op->read)(file, (char *) pstart, pend - pstart, &poff) < 0))
387                 {
388                         sys_munmap(pstart, pend - pstart);
389                         return -EINVAL;
390                 }
391                 if (!(prot & PROT_WRITE) && sys_mprotect(pstart, pend - pstart, prot) < 0)
392                         return -EINVAL;
393         }
394         return start;
395 }
396
397 #endif /* PAGE_SHIFT > IA32_PAGE_SHIFT */
398
399 static inline unsigned int
400 get_prot32 (unsigned int prot)
401 {
402         if (prot & PROT_WRITE)
403                 /* on x86, PROT_WRITE implies PROT_READ which implies PROT_EEC */
404                 prot |= PROT_READ | PROT_WRITE | PROT_EXEC;
405         else if (prot & (PROT_READ | PROT_EXEC))
406                 /* on x86, there is no distinction between PROT_READ and PROT_EXEC */
407                 prot |= (PROT_READ | PROT_EXEC);
408
409         return prot;
410 }
411
412 unsigned long
413 ia32_do_mmap (struct file *file, unsigned long addr, unsigned long len, int prot, int flags,
414               loff_t offset)
415 {
416         DBG("ia32_do_mmap(file=%p,addr=0x%lx,len=0x%lx,prot=%x,flags=%x,offset=0x%llx)\n",
417             file, addr, len, prot, flags, offset);
418
419         if (file && (!file->f_op || !file->f_op->mmap))
420                 return -ENODEV;
421
422         len = IA32_PAGE_ALIGN(len);
423         if (len == 0)
424                 return addr;
425
426         if (len > IA32_PAGE_OFFSET || addr > IA32_PAGE_OFFSET - len)
427         {
428                 if (flags & MAP_FIXED)
429                         return -ENOMEM;
430                 else
431                 return -EINVAL;
432         }
433
434         if (OFFSET4K(offset))
435                 return -EINVAL;
436
437         prot = get_prot32(prot);
438
439 #if PAGE_SHIFT > IA32_PAGE_SHIFT
440         down(&ia32_mmap_sem);
441         {
442                 addr = emulate_mmap(file, addr, len, prot, flags, offset);
443         }
444         up(&ia32_mmap_sem);
445 #else
446         down_write(&current->mm->mmap_sem);
447         {
448                 addr = do_mmap(file, addr, len, prot, flags, offset);
449         }
450         up_write(&current->mm->mmap_sem);
451 #endif
452         DBG("ia32_do_mmap: returning 0x%lx\n", addr);
453         return addr;
454 }
455
456 /*
457  * Linux/i386 didn't use to be able to handle more than 4 system call parameters, so these
458  * system calls used a memory block for parameter passing..
459  */
460
461 struct mmap_arg_struct {
462         unsigned int addr;
463         unsigned int len;
464         unsigned int prot;
465         unsigned int flags;
466         unsigned int fd;
467         unsigned int offset;
468 };
469
470 asmlinkage long
471 sys32_mmap (struct mmap_arg_struct *arg)
472 {
473         struct mmap_arg_struct a;
474         struct file *file = NULL;
475         unsigned long addr;
476         int flags;
477
478         if (copy_from_user(&a, arg, sizeof(a)))
479                 return -EFAULT;
480
481         if (OFFSET4K(a.offset))
482                 return -EINVAL;
483
484         flags = a.flags;
485
486         flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
487         if (!(flags & MAP_ANONYMOUS)) {
488                 file = fget(a.fd);
489                 if (!file)
490                         return -EBADF;
491         }
492
493         addr = ia32_do_mmap(file, a.addr, a.len, a.prot, flags, a.offset);
494
495         if (file)
496                 fput(file);
497         return addr;
498 }
499
500 asmlinkage long
501 sys32_mmap2 (unsigned int addr, unsigned int len, unsigned int prot, unsigned int flags,
502              unsigned int fd, unsigned int pgoff)
503 {
504         struct file *file = NULL;
505         unsigned long retval;
506
507         flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
508         if (!(flags & MAP_ANONYMOUS)) {
509                 file = fget(fd);
510                 if (!file)
511                         return -EBADF;
512         }
513
514         retval = ia32_do_mmap(file, addr, len, prot, flags,
515                               (unsigned long) pgoff << IA32_PAGE_SHIFT);
516
517         if (file)
518                 fput(file);
519         return retval;
520 }
521
522 asmlinkage long
523 sys32_munmap (unsigned int start, unsigned int len)
524 {
525         unsigned int end = start + len;
526         long ret;
527
528 #if PAGE_SHIFT <= IA32_PAGE_SHIFT
529         ret = sys_munmap(start, end - start);
530 #else
531         if (start >= end)
532                 return -EINVAL;
533
534         start = PAGE_ALIGN(start);
535         end = PAGE_START(end);
536
537         if (start >= end)
538                 return 0;
539
540         down(&ia32_mmap_sem);
541         {
542                 ret = sys_munmap(start, end - start);
543         }
544         up(&ia32_mmap_sem);
545 #endif
546         return ret;
547 }
548
549 #if PAGE_SHIFT > IA32_PAGE_SHIFT
550
551 /*
552  * When mprotect()ing a partial page, we set the permission to the union of the old
553  * settings and the new settings.  In other words, it's only possible to make access to a
554  * partial page less restrictive.
555  */
556 static long
557 mprotect_subpage (unsigned long address, int new_prot)
558 {
559         int old_prot;
560         struct vm_area_struct *vma;
561
562         if (new_prot == PROT_NONE)
563                 return 0;               /* optimize case where nothing changes... */
564         vma = find_vma(current->mm, address);
565         old_prot = get_page_prot(vma, address);
566         return sys_mprotect(address, PAGE_SIZE, new_prot | old_prot);
567 }
568
569 #endif /* PAGE_SHIFT > IA32_PAGE_SHIFT */
570
571 asmlinkage long
572 sys32_mprotect (unsigned int start, unsigned int len, int prot)
573 {
574         unsigned long end = start + len;
575 #if PAGE_SHIFT > IA32_PAGE_SHIFT
576         long retval = 0;
577 #endif
578
579         prot = get_prot32(prot);
580
581 #if PAGE_SHIFT <= IA32_PAGE_SHIFT
582         return sys_mprotect(start, end - start, prot);
583 #else
584         if (OFFSET4K(start))
585                 return -EINVAL;
586
587         end = IA32_PAGE_ALIGN(end);
588         if (end < start)
589                 return -EINVAL;
590
591         down(&ia32_mmap_sem);
592         {
593                 if (offset_in_page(start)) {
594                         /* start address is 4KB aligned but not page aligned. */
595                         retval = mprotect_subpage(PAGE_START(start), prot);
596                         if (retval < 0)
597                                 goto out;
598
599                         start = PAGE_ALIGN(start);
600                         if (start >= end)
601                                 goto out;       /* retval is already zero... */
602                 }
603
604                 if (offset_in_page(end)) {
605                         /* end address is 4KB aligned but not page aligned. */
606                         retval = mprotect_subpage(PAGE_START(end), prot);
607                         if (retval < 0)
608                                 goto out;
609
610                         end = PAGE_START(end);
611                 }
612                 retval = sys_mprotect(start, end - start, prot);
613         }
614   out:
615         up(&ia32_mmap_sem);
616         return retval;
617 #endif
618 }
619
620 asmlinkage long
621 sys32_pipe (int *fd)
622 {
623         int retval;
624         int fds[2];
625
626         retval = do_pipe(fds);
627         if (retval)
628                 goto out;
629         if (copy_to_user(fd, fds, sizeof(fds)))
630                 retval = -EFAULT;
631   out:
632         return retval;
633 }
634
635 static inline long
636 get_tv32 (struct timeval *o, struct compat_timeval *i)
637 {
638         return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
639                 (__get_user(o->tv_sec, &i->tv_sec) | __get_user(o->tv_usec, &i->tv_usec)));
640 }
641
642 static inline long
643 put_tv32 (struct compat_timeval *o, struct timeval *i)
644 {
645         return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
646                 (__put_user(i->tv_sec, &o->tv_sec) | __put_user(i->tv_usec, &o->tv_usec)));
647 }
648
649 asmlinkage unsigned long
650 sys32_alarm (unsigned int seconds)
651 {
652         struct itimerval it_new, it_old;
653         unsigned int oldalarm;
654
655         it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0;
656         it_new.it_value.tv_sec = seconds;
657         it_new.it_value.tv_usec = 0;
658         do_setitimer(ITIMER_REAL, &it_new, &it_old);
659         oldalarm = it_old.it_value.tv_sec;
660         /* ehhh.. We can't return 0 if we have an alarm pending.. */
661         /* And we'd better return too much than too little anyway */
662         if (it_old.it_value.tv_usec)
663                 oldalarm++;
664         return oldalarm;
665 }
666
667 /* Translations due to time_t size differences.  Which affects all
668    sorts of things, like timeval and itimerval.  */
669
670 extern struct timezone sys_tz;
671
672 asmlinkage long
673 sys32_gettimeofday (struct compat_timeval *tv, struct timezone *tz)
674 {
675         if (tv) {
676                 struct timeval ktv;
677                 do_gettimeofday(&ktv);
678                 if (put_tv32(tv, &ktv))
679                         return -EFAULT;
680         }
681         if (tz) {
682                 if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
683                         return -EFAULT;
684         }
685         return 0;
686 }
687
688 asmlinkage long
689 sys32_settimeofday (struct compat_timeval *tv, struct timezone *tz)
690 {
691         struct timeval ktv;
692         struct timespec kts;
693         struct timezone ktz;
694
695         if (tv) {
696                 if (get_tv32(&ktv, tv))
697                         return -EFAULT;
698                 kts.tv_sec = ktv.tv_sec;
699                 kts.tv_nsec = ktv.tv_usec * 1000;
700         }
701         if (tz) {
702                 if (copy_from_user(&ktz, tz, sizeof(ktz)))
703                         return -EFAULT;
704         }
705
706         return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
707 }
708
709 struct getdents32_callback {
710         struct compat_dirent * current_dir;
711         struct compat_dirent * previous;
712         int count;
713         int error;
714 };
715
716 struct readdir32_callback {
717         struct old_linux32_dirent * dirent;
718         int count;
719 };
720
721 static int
722 filldir32 (void *__buf, const char *name, int namlen, loff_t offset, ino_t ino,
723            unsigned int d_type)
724 {
725         struct compat_dirent * dirent;
726         struct getdents32_callback * buf = (struct getdents32_callback *) __buf;
727         int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1, 4);
728
729         buf->error = -EINVAL;   /* only used if we fail.. */
730         if (reclen > buf->count)
731                 return -EINVAL;
732         buf->error = -EFAULT;   /* only used if we fail.. */
733         dirent = buf->previous;
734         if (dirent)
735                 if (put_user(offset, &dirent->d_off))
736                         return -EFAULT;
737         dirent = buf->current_dir;
738         buf->previous = dirent;
739         if (put_user(ino, &dirent->d_ino)
740             || put_user(reclen, &dirent->d_reclen)
741             || copy_to_user(dirent->d_name, name, namlen)
742             || put_user(0, dirent->d_name + namlen))
743                 return -EFAULT;
744         dirent = (struct compat_dirent *) ((char *) dirent + reclen);
745         buf->current_dir = dirent;
746         buf->count -= reclen;
747         return 0;
748 }
749
750 asmlinkage long
751 sys32_getdents (unsigned int fd, struct compat_dirent *dirent, unsigned int count)
752 {
753         struct file * file;
754         struct compat_dirent * lastdirent;
755         struct getdents32_callback buf;
756         int error;
757
758         error = -EBADF;
759         file = fget(fd);
760         if (!file)
761                 goto out;
762
763         buf.current_dir = dirent;
764         buf.previous = NULL;
765         buf.count = count;
766         buf.error = 0;
767
768         error = vfs_readdir(file, filldir32, &buf);
769         if (error < 0)
770                 goto out_putf;
771         error = buf.error;
772         lastdirent = buf.previous;
773         if (lastdirent) {
774                 error = -EINVAL;
775                 if (put_user(file->f_pos, &lastdirent->d_off))
776                         goto out_putf;
777                 error = count - buf.count;
778         }
779
780 out_putf:
781         fput(file);
782 out:
783         return error;
784 }
785
786 static int
787 fillonedir32 (void * __buf, const char * name, int namlen, loff_t offset, ino_t ino,
788               unsigned int d_type)
789 {
790         struct readdir32_callback * buf = (struct readdir32_callback *) __buf;
791         struct old_linux32_dirent * dirent;
792
793         if (buf->count)
794                 return -EINVAL;
795         buf->count++;
796         dirent = buf->dirent;
797         if (put_user(ino, &dirent->d_ino)
798             || put_user(offset, &dirent->d_offset)
799             || put_user(namlen, &dirent->d_namlen)
800             || copy_to_user(dirent->d_name, name, namlen)
801             || put_user(0, dirent->d_name + namlen))
802                 return -EFAULT;
803         return 0;
804 }
805
806 asmlinkage long
807 sys32_readdir (unsigned int fd, void *dirent, unsigned int count)
808 {
809         int error;
810         struct file * file;
811         struct readdir32_callback buf;
812
813         error = -EBADF;
814         file = fget(fd);
815         if (!file)
816                 goto out;
817
818         buf.count = 0;
819         buf.dirent = dirent;
820
821         error = vfs_readdir(file, fillonedir32, &buf);
822         if (error >= 0)
823                 error = buf.count;
824         fput(file);
825 out:
826         return error;
827 }
828
829 /*
830  * We can actually return ERESTARTSYS instead of EINTR, but I'd
831  * like to be certain this leads to no problems. So I return
832  * EINTR just for safety.
833  *
834  * Update: ERESTARTSYS breaks at least the xview clock binary, so
835  * I'm trying ERESTARTNOHAND which restart only when you want to.
836  */
837 #define MAX_SELECT_SECONDS \
838         ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
839 #define ROUND_UP_TIME(x,y) (((x)+(y)-1)/(y))
840
841 asmlinkage long
842 sys32_select (int n, fd_set *inp, fd_set *outp, fd_set *exp, struct compat_timeval *tvp32)
843 {
844         fd_set_bits fds;
845         char *bits;
846         long timeout;
847         int ret, size;
848
849         timeout = MAX_SCHEDULE_TIMEOUT;
850         if (tvp32) {
851                 time_t sec, usec;
852
853                 ret = -EFAULT;
854                 if (get_user(sec, &tvp32->tv_sec) || get_user(usec, &tvp32->tv_usec))
855                         goto out_nofds;
856
857                 ret = -EINVAL;
858                 if (sec < 0 || usec < 0)
859                         goto out_nofds;
860
861                 if ((unsigned long) sec < MAX_SELECT_SECONDS) {
862                         timeout = ROUND_UP_TIME(usec, 1000000/HZ);
863                         timeout += sec * (unsigned long) HZ;
864                 }
865         }
866
867         ret = -EINVAL;
868         if (n < 0)
869                 goto out_nofds;
870
871         if (n > current->files->max_fdset)
872                 n = current->files->max_fdset;
873
874         /*
875          * We need 6 bitmaps (in/out/ex for both incoming and outgoing),
876          * since we used fdset we need to allocate memory in units of
877          * long-words.
878          */
879         ret = -ENOMEM;
880         size = FDS_BYTES(n);
881         bits = kmalloc(6 * size, GFP_KERNEL);
882         if (!bits)
883                 goto out_nofds;
884         fds.in      = (unsigned long *)  bits;
885         fds.out     = (unsigned long *) (bits +   size);
886         fds.ex      = (unsigned long *) (bits + 2*size);
887         fds.res_in  = (unsigned long *) (bits + 3*size);
888         fds.res_out = (unsigned long *) (bits + 4*size);
889         fds.res_ex  = (unsigned long *) (bits + 5*size);
890
891         if ((ret = get_fd_set(n, inp, fds.in)) ||
892             (ret = get_fd_set(n, outp, fds.out)) ||
893             (ret = get_fd_set(n, exp, fds.ex)))
894                 goto out;
895         zero_fd_set(n, fds.res_in);
896         zero_fd_set(n, fds.res_out);
897         zero_fd_set(n, fds.res_ex);
898
899         ret = do_select(n, &fds, &timeout);
900
901         if (tvp32 && !(current->personality & STICKY_TIMEOUTS)) {
902                 time_t sec = 0, usec = 0;
903                 if (timeout) {
904                         sec = timeout / HZ;
905                         usec = timeout % HZ;
906                         usec *= (1000000/HZ);
907                 }
908                 if (put_user(sec, &tvp32->tv_sec) || put_user(usec, &tvp32->tv_usec)) {
909                         ret = -EFAULT;
910                         goto out;
911                 }
912         }
913
914         if (ret < 0)
915                 goto out;
916         if (!ret) {
917                 ret = -ERESTARTNOHAND;
918                 if (signal_pending(current))
919                         goto out;
920                 ret = 0;
921         }
922
923         set_fd_set(n, inp, fds.res_in);
924         set_fd_set(n, outp, fds.res_out);
925         set_fd_set(n, exp, fds.res_ex);
926
927 out:
928         kfree(bits);
929 out_nofds:
930         return ret;
931 }
932
933 struct sel_arg_struct {
934         unsigned int n;
935         unsigned int inp;
936         unsigned int outp;
937         unsigned int exp;
938         unsigned int tvp;
939 };
940
941 asmlinkage long
942 sys32_old_select (struct sel_arg_struct *arg)
943 {
944         struct sel_arg_struct a;
945
946         if (copy_from_user(&a, arg, sizeof(a)))
947                 return -EFAULT;
948         return sys32_select(a.n, (fd_set *) A(a.inp), (fd_set *) A(a.outp), (fd_set *) A(a.exp),
949                             (struct compat_timeval *) A(a.tvp));
950 }
951
952 asmlinkage ssize_t sys_readv (unsigned long,const struct iovec *,unsigned long);
953 asmlinkage ssize_t sys_writev (unsigned long,const struct iovec *,unsigned long);
954
955 static struct iovec *
956 get_compat_iovec (struct compat_iovec *iov32, struct iovec *iov_buf, u32 count, int type)
957 {
958         u32 i, buf, len;
959         struct iovec *ivp, *iov;
960
961         /* Get the "struct iovec" from user memory */
962
963         if (!count)
964                 return 0;
965         if (verify_area(VERIFY_READ, iov32, sizeof(struct compat_iovec)*count))
966                 return NULL;
967         if (count > UIO_MAXIOV)
968                 return NULL;
969         if (count > UIO_FASTIOV) {
970                 iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL);
971                 if (!iov)
972                         return NULL;
973         } else
974                 iov = iov_buf;
975
976         ivp = iov;
977         for (i = 0; i < count; i++) {
978                 if (__get_user(len, &iov32->iov_len) || __get_user(buf, &iov32->iov_base)) {
979                         if (iov != iov_buf)
980                                 kfree(iov);
981                         return NULL;
982                 }
983                 if (verify_area(type, (void *)A(buf), len)) {
984                         if (iov != iov_buf)
985                                 kfree(iov);
986                         return((struct iovec *)0);
987                 }
988                 ivp->iov_base = (void *)A(buf);
989                 ivp->iov_len = (__kernel_size_t) len;
990                 iov32++;
991                 ivp++;
992         }
993         return iov;
994 }
995
996 asmlinkage long
997 sys32_readv (int fd, struct compat_iovec *vector, u32 count)
998 {
999         struct iovec iovstack[UIO_FASTIOV];
1000         struct iovec *iov;
1001         long ret;
1002         mm_segment_t old_fs = get_fs();
1003
1004         iov = get_compat_iovec(vector, iovstack, count, VERIFY_WRITE);
1005         if (!iov)
1006                 return -EFAULT;
1007         set_fs(KERNEL_DS);
1008         ret = sys_readv(fd, iov, count);
1009         set_fs(old_fs);
1010         if (iov != iovstack)
1011                 kfree(iov);
1012         return ret;
1013 }
1014
1015 asmlinkage long
1016 sys32_writev (int fd, struct compat_iovec *vector, u32 count)
1017 {
1018         struct iovec iovstack[UIO_FASTIOV];
1019         struct iovec *iov;
1020         long ret;
1021         mm_segment_t old_fs = get_fs();
1022
1023         iov = get_compat_iovec(vector, iovstack, count, VERIFY_READ);
1024         if (!iov)
1025                 return -EFAULT;
1026         set_fs(KERNEL_DS);
1027         ret = sys_writev(fd, iov, count);
1028         set_fs(old_fs);
1029         if (iov != iovstack)
1030                 kfree(iov);
1031         return ret;
1032 }
1033
1034 /*
1035  * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation..
1036  *
1037  * This is really horribly ugly.
1038  */
1039
1040 struct msgbuf32 { s32 mtype; char mtext[1]; };
1041
1042 struct ipc_perm32 {
1043         key_t key;
1044         compat_uid_t uid;
1045         compat_gid_t gid;
1046         compat_uid_t cuid;
1047         compat_gid_t cgid;
1048         compat_mode_t mode;
1049         unsigned short seq;
1050 };
1051
1052 struct ipc64_perm32 {
1053         key_t key;
1054         compat_uid32_t uid;
1055         compat_gid32_t gid;
1056         compat_uid32_t cuid;
1057         compat_gid32_t cgid;
1058         compat_mode_t mode;
1059         unsigned short __pad1;
1060         unsigned short seq;
1061         unsigned short __pad2;
1062         unsigned int unused1;
1063         unsigned int unused2;
1064 };
1065
1066 struct semid_ds32 {
1067         struct ipc_perm32 sem_perm;               /* permissions .. see ipc.h */
1068         compat_time_t   sem_otime;              /* last semop time */
1069         compat_time_t   sem_ctime;              /* last change time */
1070         u32 sem_base;              /* ptr to first semaphore in array */
1071         u32 sem_pending;          /* pending operations to be processed */
1072         u32 sem_pending_last;    /* last pending operation */
1073         u32 undo;                  /* undo requests on this array */
1074         unsigned short  sem_nsems;              /* no. of semaphores in array */
1075 };
1076
1077 struct semid64_ds32 {
1078         struct ipc64_perm32 sem_perm;
1079         compat_time_t   sem_otime;
1080         unsigned int __unused1;
1081         compat_time_t   sem_ctime;
1082         unsigned int __unused2;
1083         unsigned int sem_nsems;
1084         unsigned int __unused3;
1085         unsigned int __unused4;
1086 };
1087
1088 struct msqid_ds32 {
1089         struct ipc_perm32 msg_perm;
1090         u32 msg_first;
1091         u32 msg_last;
1092         compat_time_t   msg_stime;
1093         compat_time_t   msg_rtime;
1094         compat_time_t   msg_ctime;
1095         u32 wwait;
1096         u32 rwait;
1097         unsigned short msg_cbytes;
1098         unsigned short msg_qnum;
1099         unsigned short msg_qbytes;
1100         compat_ipc_pid_t msg_lspid;
1101         compat_ipc_pid_t msg_lrpid;
1102 };
1103
1104 struct msqid64_ds32 {
1105         struct ipc64_perm32 msg_perm;
1106         compat_time_t   msg_stime;
1107         unsigned int __unused1;
1108         compat_time_t   msg_rtime;
1109         unsigned int __unused2;
1110         compat_time_t   msg_ctime;
1111         unsigned int __unused3;
1112         unsigned int msg_cbytes;
1113         unsigned int msg_qnum;
1114         unsigned int msg_qbytes;
1115         compat_pid_t msg_lspid;
1116         compat_pid_t msg_lrpid;
1117         unsigned int __unused4;
1118         unsigned int __unused5;
1119 };
1120
1121 struct shmid_ds32 {
1122         struct ipc_perm32 shm_perm;
1123         int shm_segsz;
1124         compat_time_t   shm_atime;
1125         compat_time_t   shm_dtime;
1126         compat_time_t   shm_ctime;
1127         compat_ipc_pid_t shm_cpid;
1128         compat_ipc_pid_t shm_lpid;
1129         unsigned short shm_nattch;
1130 };
1131
1132 struct shmid64_ds32 {
1133         struct ipc64_perm32 shm_perm;
1134         compat_size_t shm_segsz;
1135         compat_time_t   shm_atime;
1136         unsigned int __unused1;
1137         compat_time_t   shm_dtime;
1138         unsigned int __unused2;
1139         compat_time_t   shm_ctime;
1140         unsigned int __unused3;
1141         compat_pid_t shm_cpid;
1142         compat_pid_t shm_lpid;
1143         unsigned int shm_nattch;
1144         unsigned int __unused4;
1145         unsigned int __unused5;
1146 };
1147
1148 struct shminfo64_32 {
1149         unsigned int shmmax;
1150         unsigned int shmmin;
1151         unsigned int shmmni;
1152         unsigned int shmseg;
1153         unsigned int shmall;
1154         unsigned int __unused1;
1155         unsigned int __unused2;
1156         unsigned int __unused3;
1157         unsigned int __unused4;
1158 };
1159
1160 struct shm_info32 {
1161         int used_ids;
1162         u32 shm_tot, shm_rss, shm_swp;
1163         u32 swap_attempts, swap_successes;
1164 };
1165
1166 struct ipc_kludge {
1167         u32 msgp;
1168         s32 msgtyp;
1169 };
1170
1171 #define SEMOP            1
1172 #define SEMGET           2
1173 #define SEMCTL           3
1174 #define SEMTIMEDOP       4
1175 #define MSGSND          11
1176 #define MSGRCV          12
1177 #define MSGGET          13
1178 #define MSGCTL          14
1179 #define SHMAT           21
1180 #define SHMDT           22
1181 #define SHMGET          23
1182 #define SHMCTL          24
1183
1184 #define IPCOP_MASK(__x) (1UL << (__x))
1185
1186 static int
1187 ipc_parse_version32 (int *cmd)
1188 {
1189         if (*cmd & IPC_64) {
1190                 *cmd ^= IPC_64;
1191                 return IPC_64;
1192         } else {
1193                 return IPC_OLD;
1194         }
1195 }
1196
1197 static int
1198 semctl32 (int first, int second, int third, void *uptr)
1199 {
1200         union semun fourth;
1201         u32 pad;
1202         int err = 0, err2;
1203         struct semid64_ds s;
1204         mm_segment_t old_fs;
1205         int version = ipc_parse_version32(&third);
1206
1207         if (!uptr)
1208                 return -EINVAL;
1209         if (get_user(pad, (u32 *)uptr))
1210                 return -EFAULT;
1211         if (third == SETVAL)
1212                 fourth.val = (int)pad;
1213         else
1214                 fourth.__pad = (void *)A(pad);
1215         switch (third) {
1216               default:
1217                 err = -EINVAL;
1218                 break;
1219
1220               case IPC_INFO:
1221               case IPC_RMID:
1222               case IPC_SET:
1223               case SEM_INFO:
1224               case GETVAL:
1225               case GETPID:
1226               case GETNCNT:
1227               case GETZCNT:
1228               case GETALL:
1229               case SETVAL:
1230               case SETALL:
1231                 err = sys_semctl(first, second, third, fourth);
1232                 break;
1233
1234               case IPC_STAT:
1235               case SEM_STAT:
1236                 fourth.__pad = &s;
1237                 old_fs = get_fs();
1238                 set_fs(KERNEL_DS);
1239                 err = sys_semctl(first, second, third, fourth);
1240                 set_fs(old_fs);
1241
1242                 if (version == IPC_64) {
1243                         struct semid64_ds32 *usp64 = (struct semid64_ds32 *) A(pad);
1244
1245                         if (!access_ok(VERIFY_WRITE, usp64, sizeof(*usp64))) {
1246                                 err = -EFAULT;
1247                                 break;
1248                         }
1249                         err2 = __put_user(s.sem_perm.key, &usp64->sem_perm.key);
1250                         err2 |= __put_user(s.sem_perm.uid, &usp64->sem_perm.uid);
1251                         err2 |= __put_user(s.sem_perm.gid, &usp64->sem_perm.gid);
1252                         err2 |= __put_user(s.sem_perm.cuid, &usp64->sem_perm.cuid);
1253                         err2 |= __put_user(s.sem_perm.cgid, &usp64->sem_perm.cgid);
1254                         err2 |= __put_user(s.sem_perm.mode, &usp64->sem_perm.mode);
1255                         err2 |= __put_user(s.sem_perm.seq, &usp64->sem_perm.seq);
1256                         err2 |= __put_user(s.sem_otime, &usp64->sem_otime);
1257                         err2 |= __put_user(s.sem_ctime, &usp64->sem_ctime);
1258                         err2 |= __put_user(s.sem_nsems, &usp64->sem_nsems);
1259                 } else {
1260                         struct semid_ds32 *usp32 = (struct semid_ds32 *) A(pad);
1261
1262                         if (!access_ok(VERIFY_WRITE, usp32, sizeof(*usp32))) {
1263                                 err = -EFAULT;
1264                                 break;
1265                         }
1266                         err2 = __put_user(s.sem_perm.key, &usp32->sem_perm.key);
1267                         err2 |= __put_user(s.sem_perm.uid, &usp32->sem_perm.uid);
1268                         err2 |= __put_user(s.sem_perm.gid, &usp32->sem_perm.gid);
1269                         err2 |= __put_user(s.sem_perm.cuid, &usp32->sem_perm.cuid);
1270                         err2 |= __put_user(s.sem_perm.cgid, &usp32->sem_perm.cgid);
1271                         err2 |= __put_user(s.sem_perm.mode, &usp32->sem_perm.mode);
1272                         err2 |= __put_user(s.sem_perm.seq, &usp32->sem_perm.seq);
1273                         err2 |= __put_user(s.sem_otime, &usp32->sem_otime);
1274                         err2 |= __put_user(s.sem_ctime, &usp32->sem_ctime);
1275                         err2 |= __put_user(s.sem_nsems, &usp32->sem_nsems);
1276                 }
1277                 if (err2)
1278                     err = -EFAULT;
1279                 break;
1280         }
1281         return err;
1282 }
1283
1284 static int
1285 do_sys32_msgsnd (int first, int second, int third, void *uptr)
1286 {
1287         struct msgbuf *p = kmalloc(second + sizeof(struct msgbuf), GFP_USER);
1288         struct msgbuf32 *up = (struct msgbuf32 *)uptr;
1289         mm_segment_t old_fs;
1290         int err;
1291
1292         if (!p)
1293                 return -ENOMEM;
1294         err = get_user(p->mtype, &up->mtype);
1295         err |= copy_from_user(p->mtext, &up->mtext, second);
1296         if (err)
1297                 goto out;
1298         old_fs = get_fs();
1299         set_fs(KERNEL_DS);
1300         err = sys_msgsnd(first, p, second, third);
1301         set_fs(old_fs);
1302   out:
1303         kfree(p);
1304         return err;
1305 }
1306
1307 static int
1308 do_sys32_msgrcv (int first, int second, int msgtyp, int third, int version, void *uptr)
1309 {
1310         struct msgbuf32 *up;
1311         struct msgbuf *p;
1312         mm_segment_t old_fs;
1313         int err;
1314
1315         if (!version) {
1316                 struct ipc_kludge *uipck = (struct ipc_kludge *)uptr;
1317                 struct ipc_kludge ipck;
1318
1319                 err = -EINVAL;
1320                 if (!uptr)
1321                         goto out;
1322                 err = -EFAULT;
1323                 if (copy_from_user(&ipck, uipck, sizeof(struct ipc_kludge)))
1324                         goto out;
1325                 uptr = (void *)A(ipck.msgp);
1326                 msgtyp = ipck.msgtyp;
1327         }
1328         err = -ENOMEM;
1329         p = kmalloc(second + sizeof(struct msgbuf), GFP_USER);
1330         if (!p)
1331                 goto out;
1332         old_fs = get_fs();
1333         set_fs(KERNEL_DS);
1334         err = sys_msgrcv(first, p, second, msgtyp, third);
1335         set_fs(old_fs);
1336         if (err < 0)
1337                 goto free_then_out;
1338         up = (struct msgbuf32 *)uptr;
1339         if (put_user(p->mtype, &up->mtype) || copy_to_user(&up->mtext, p->mtext, err))
1340                 err = -EFAULT;
1341 free_then_out:
1342         kfree(p);
1343 out:
1344         return err;
1345 }
1346
1347 static int
1348 msgctl32 (int first, int second, void *uptr)
1349 {
1350         int err = -EINVAL, err2;
1351         struct msqid64_ds m64;
1352         struct msqid_ds32 *up32 = (struct msqid_ds32 *)uptr;
1353         struct msqid64_ds32 *up64 = (struct msqid64_ds32 *)uptr;
1354         mm_segment_t old_fs;
1355         int version = ipc_parse_version32(&second);
1356
1357         switch (second) {
1358               case IPC_INFO:
1359               case IPC_RMID:
1360               case MSG_INFO:
1361                 err = sys_msgctl(first, second, (struct msqid_ds *)uptr);
1362                 break;
1363
1364               case IPC_SET:
1365                 if (version == IPC_64) {
1366                         err = get_user(m64.msg_perm.uid, &up64->msg_perm.uid);
1367                         err |= get_user(m64.msg_perm.gid, &up64->msg_perm.gid);
1368                         err |= get_user(m64.msg_perm.mode, &up64->msg_perm.mode);
1369                         err |= get_user(m64.msg_qbytes, &up64->msg_qbytes);
1370                 } else {
1371                         err = get_user(m64.msg_perm.uid, &up32->msg_perm.uid);
1372                         err |= get_user(m64.msg_perm.gid, &up32->msg_perm.gid);
1373                         err |= get_user(m64.msg_perm.mode, &up32->msg_perm.mode);
1374                         err |= get_user(m64.msg_qbytes, &up32->msg_qbytes);
1375                 }
1376                 if (err)
1377                         break;
1378                 old_fs = get_fs();
1379                 set_fs(KERNEL_DS);
1380                 err = sys_msgctl(first, second, (struct msqid_ds *)&m64);
1381                 set_fs(old_fs);
1382                 break;
1383
1384               case IPC_STAT:
1385               case MSG_STAT:
1386                 old_fs = get_fs();
1387                 set_fs(KERNEL_DS);
1388                 err = sys_msgctl(first, second, (struct msqid_ds *)&m64);
1389                 set_fs(old_fs);
1390
1391                 if (version == IPC_64) {
1392                         if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) {
1393                                 err = -EFAULT;
1394                                 break;
1395                         }
1396                         err2 = __put_user(m64.msg_perm.key, &up64->msg_perm.key);
1397                         err2 |= __put_user(m64.msg_perm.uid, &up64->msg_perm.uid);
1398                         err2 |= __put_user(m64.msg_perm.gid, &up64->msg_perm.gid);
1399                         err2 |= __put_user(m64.msg_perm.cuid, &up64->msg_perm.cuid);
1400                         err2 |= __put_user(m64.msg_perm.cgid, &up64->msg_perm.cgid);
1401                         err2 |= __put_user(m64.msg_perm.mode, &up64->msg_perm.mode);
1402                         err2 |= __put_user(m64.msg_perm.seq, &up64->msg_perm.seq);
1403                         err2 |= __put_user(m64.msg_stime, &up64->msg_stime);
1404                         err2 |= __put_user(m64.msg_rtime, &up64->msg_rtime);
1405                         err2 |= __put_user(m64.msg_ctime, &up64->msg_ctime);
1406                         err2 |= __put_user(m64.msg_cbytes, &up64->msg_cbytes);
1407                         err2 |= __put_user(m64.msg_qnum, &up64->msg_qnum);
1408                         err2 |= __put_user(m64.msg_qbytes, &up64->msg_qbytes);
1409                         err2 |= __put_user(m64.msg_lspid, &up64->msg_lspid);
1410                         err2 |= __put_user(m64.msg_lrpid, &up64->msg_lrpid);
1411                         if (err2)
1412                                 err = -EFAULT;
1413                 } else {
1414                         if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) {
1415                                 err = -EFAULT;
1416                                 break;
1417                         }
1418                         err2 = __put_user(m64.msg_perm.key, &up32->msg_perm.key);
1419                         err2 |= __put_user(m64.msg_perm.uid, &up32->msg_perm.uid);
1420                         err2 |= __put_user(m64.msg_perm.gid, &up32->msg_perm.gid);
1421                         err2 |= __put_user(m64.msg_perm.cuid, &up32->msg_perm.cuid);
1422                         err2 |= __put_user(m64.msg_perm.cgid, &up32->msg_perm.cgid);
1423                         err2 |= __put_user(m64.msg_perm.mode, &up32->msg_perm.mode);
1424                         err2 |= __put_user(m64.msg_perm.seq, &up32->msg_perm.seq);
1425                         err2 |= __put_user(m64.msg_stime, &up32->msg_stime);
1426                         err2 |= __put_user(m64.msg_rtime, &up32->msg_rtime);
1427                         err2 |= __put_user(m64.msg_ctime, &up32->msg_ctime);
1428                         err2 |= __put_user(m64.msg_cbytes, &up32->msg_cbytes);
1429                         err2 |= __put_user(m64.msg_qnum, &up32->msg_qnum);
1430                         err2 |= __put_user(m64.msg_qbytes, &up32->msg_qbytes);
1431                         err2 |= __put_user(m64.msg_lspid, &up32->msg_lspid);
1432                         err2 |= __put_user(m64.msg_lrpid, &up32->msg_lrpid);
1433                         if (err2)
1434                                 err = -EFAULT;
1435                 }
1436                 break;
1437         }
1438         return err;
1439 }
1440
1441 static int
1442 shmat32 (int first, int second, int third, int version, void *uptr)
1443 {
1444         unsigned long raddr;
1445         u32 *uaddr = (u32 *)A((u32)third);
1446         int err;
1447
1448         if (version == 1)
1449                 return -EINVAL; /* iBCS2 emulator entry point: unsupported */
1450         err = sys_shmat(first, uptr, second, &raddr);
1451         if (err)
1452                 return err;
1453         return put_user(raddr, uaddr);
1454 }
1455
1456 static int
1457 shmctl32 (int first, int second, void *uptr)
1458 {
1459         int err = -EFAULT, err2;
1460
1461         struct shmid64_ds s64;
1462         struct shmid_ds32 *up32 = (struct shmid_ds32 *)uptr;
1463         struct shmid64_ds32 *up64 = (struct shmid64_ds32 *)uptr;
1464         mm_segment_t old_fs;
1465         struct shm_info32 *uip = (struct shm_info32 *)uptr;
1466         struct shm_info si;
1467         int version = ipc_parse_version32(&second);
1468         struct shminfo64 smi;
1469         struct shminfo *usi32 = (struct shminfo *) uptr;
1470         struct shminfo64_32 *usi64 = (struct shminfo64_32 *) uptr;
1471
1472         switch (second) {
1473               case IPC_INFO:
1474                 old_fs = get_fs();
1475                 set_fs(KERNEL_DS);
1476                 err = sys_shmctl(first, second, (struct shmid_ds *)&smi);
1477                 set_fs(old_fs);
1478
1479                 if (version == IPC_64) {
1480                         if (!access_ok(VERIFY_WRITE, usi64, sizeof(*usi64))) {
1481                                 err = -EFAULT;
1482                                 break;
1483                         }
1484                         err2 = __put_user(smi.shmmax, &usi64->shmmax);
1485                         err2 |= __put_user(smi.shmmin, &usi64->shmmin);
1486                         err2 |= __put_user(smi.shmmni, &usi64->shmmni);
1487                         err2 |= __put_user(smi.shmseg, &usi64->shmseg);
1488                         err2 |= __put_user(smi.shmall, &usi64->shmall);
1489                 } else {
1490                         if (!access_ok(VERIFY_WRITE, usi32, sizeof(*usi32))) {
1491                                 err = -EFAULT;
1492                                 break;
1493                         }
1494                         err2 = __put_user(smi.shmmax, &usi32->shmmax);
1495                         err2 |= __put_user(smi.shmmin, &usi32->shmmin);
1496                         err2 |= __put_user(smi.shmmni, &usi32->shmmni);
1497                         err2 |= __put_user(smi.shmseg, &usi32->shmseg);
1498                         err2 |= __put_user(smi.shmall, &usi32->shmall);
1499                 }
1500                 if (err2)
1501                         err = -EFAULT;
1502                 break;
1503
1504               case IPC_RMID:
1505               case SHM_LOCK:
1506               case SHM_UNLOCK:
1507                 err = sys_shmctl(first, second, (struct shmid_ds *)uptr);
1508                 break;
1509
1510               case IPC_SET:
1511                 if (version == IPC_64) {
1512                         err = get_user(s64.shm_perm.uid, &up64->shm_perm.uid);
1513                         err |= get_user(s64.shm_perm.gid, &up64->shm_perm.gid);
1514                         err |= get_user(s64.shm_perm.mode, &up64->shm_perm.mode);
1515                 } else {
1516                         err = get_user(s64.shm_perm.uid, &up32->shm_perm.uid);
1517                         err |= get_user(s64.shm_perm.gid, &up32->shm_perm.gid);
1518                         err |= get_user(s64.shm_perm.mode, &up32->shm_perm.mode);
1519                 }
1520                 if (err)
1521                         break;
1522                 old_fs = get_fs();
1523                 set_fs(KERNEL_DS);
1524                 err = sys_shmctl(first, second, (struct shmid_ds *)&s64);
1525                 set_fs(old_fs);
1526                 break;
1527
1528               case IPC_STAT:
1529               case SHM_STAT:
1530                 old_fs = get_fs();
1531                 set_fs(KERNEL_DS);
1532                 err = sys_shmctl(first, second, (struct shmid_ds *)&s64);
1533                 set_fs(old_fs);
1534                 if (err < 0)
1535                         break;
1536                 if (version == IPC_64) {
1537                         if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) {
1538                                 err = -EFAULT;
1539                                 break;
1540                         }
1541                         err2 = __put_user(s64.shm_perm.key, &up64->shm_perm.key);
1542                         err2 |= __put_user(s64.shm_perm.uid, &up64->shm_perm.uid);
1543                         err2 |= __put_user(s64.shm_perm.gid, &up64->shm_perm.gid);
1544                         err2 |= __put_user(s64.shm_perm.cuid, &up64->shm_perm.cuid);
1545                         err2 |= __put_user(s64.shm_perm.cgid, &up64->shm_perm.cgid);
1546                         err2 |= __put_user(s64.shm_perm.mode, &up64->shm_perm.mode);
1547                         err2 |= __put_user(s64.shm_perm.seq, &up64->shm_perm.seq);
1548                         err2 |= __put_user(s64.shm_atime, &up64->shm_atime);
1549                         err2 |= __put_user(s64.shm_dtime, &up64->shm_dtime);
1550                         err2 |= __put_user(s64.shm_ctime, &up64->shm_ctime);
1551                         err2 |= __put_user(s64.shm_segsz, &up64->shm_segsz);
1552                         err2 |= __put_user(s64.shm_nattch, &up64->shm_nattch);
1553                         err2 |= __put_user(s64.shm_cpid, &up64->shm_cpid);
1554                         err2 |= __put_user(s64.shm_lpid, &up64->shm_lpid);
1555                 } else {
1556                         if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) {
1557                                 err = -EFAULT;
1558                                 break;
1559                         }
1560                         err2 = __put_user(s64.shm_perm.key, &up32->shm_perm.key);
1561                         err2 |= __put_user(s64.shm_perm.uid, &up32->shm_perm.uid);
1562                         err2 |= __put_user(s64.shm_perm.gid, &up32->shm_perm.gid);
1563                         err2 |= __put_user(s64.shm_perm.cuid, &up32->shm_perm.cuid);
1564                         err2 |= __put_user(s64.shm_perm.cgid, &up32->shm_perm.cgid);
1565                         err2 |= __put_user(s64.shm_perm.mode, &up32->shm_perm.mode);
1566                         err2 |= __put_user(s64.shm_perm.seq, &up32->shm_perm.seq);
1567                         err2 |= __put_user(s64.shm_atime, &up32->shm_atime);
1568                         err2 |= __put_user(s64.shm_dtime, &up32->shm_dtime);
1569                         err2 |= __put_user(s64.shm_ctime, &up32->shm_ctime);
1570                         err2 |= __put_user(s64.shm_segsz, &up32->shm_segsz);
1571                         err2 |= __put_user(s64.shm_nattch, &up32->shm_nattch);
1572                         err2 |= __put_user(s64.shm_cpid, &up32->shm_cpid);
1573                         err2 |= __put_user(s64.shm_lpid, &up32->shm_lpid);
1574                 }
1575                 if (err2)
1576                         err = -EFAULT;
1577                 break;
1578
1579               case SHM_INFO:
1580                 old_fs = get_fs();
1581                 set_fs(KERNEL_DS);
1582                 err = sys_shmctl(first, second, (void *)&si);
1583                 set_fs(old_fs);
1584                 if (err < 0)
1585                         break;
1586
1587                 if (!access_ok(VERIFY_WRITE, uip, sizeof(*uip))) {
1588                         err = -EFAULT;
1589                         break;
1590                 }
1591                 err2 = __put_user(si.used_ids, &uip->used_ids);
1592                 err2 |= __put_user(si.shm_tot, &uip->shm_tot);
1593                 err2 |= __put_user(si.shm_rss, &uip->shm_rss);
1594                 err2 |= __put_user(si.shm_swp, &uip->shm_swp);
1595                 err2 |= __put_user(si.swap_attempts, &uip->swap_attempts);
1596                 err2 |= __put_user(si.swap_successes, &uip->swap_successes);
1597                 if (err2)
1598                         err = -EFAULT;
1599                 break;
1600
1601         }
1602         return err;
1603 }
1604
1605 extern int sem_ctls[];
1606 #define sc_semopm       (sem_ctls[2])
1607
1608 static long
1609 semtimedop32(int semid, struct sembuf *tsops, int nsops,
1610              struct compat_timespec *timeout32)
1611 {
1612         struct timespec t;
1613         mm_segment_t oldfs;
1614         long ret;
1615
1616         /* parameter checking precedence should mirror sys_semtimedop() */
1617         if (nsops < 1 || semid < 0)
1618                 return -EINVAL;
1619         if (nsops > sc_semopm)
1620                 return -E2BIG;
1621         if (!access_ok(VERIFY_READ, tsops, nsops * sizeof(struct sembuf)) ||
1622             get_compat_timespec(&t, timeout32))
1623                 return -EFAULT;
1624
1625         oldfs = get_fs();
1626         set_fs(KERNEL_DS);
1627         ret = sys_semtimedop(semid, tsops, nsops, &t);
1628         set_fs(oldfs);
1629         return ret;
1630 }
1631
1632 asmlinkage long
1633 sys32_ipc(u32 call, int first, int second, int third, u32 ptr, u32 fifth)
1634 {
1635         int version;
1636
1637         version = call >> 16; /* hack for backward compatibility */
1638         call &= 0xffff;
1639
1640         switch (call) {
1641               case SEMTIMEDOP:
1642                 if (fifth)
1643                         return semtimedop32(first, (struct sembuf *)AA(ptr),
1644                                 second, (struct compat_timespec *)AA(fifth));
1645                 /* else fall through for normal semop() */
1646               case SEMOP:
1647                 /* struct sembuf is the same on 32 and 64bit :)) */
1648                 return sys_semtimedop(first, (struct sembuf *)AA(ptr), second,
1649                                       NULL);
1650               case SEMGET:
1651                 return sys_semget(first, second, third);
1652               case SEMCTL:
1653                 return semctl32(first, second, third, (void *)AA(ptr));
1654
1655               case MSGSND:
1656                 return do_sys32_msgsnd(first, second, third, (void *)AA(ptr));
1657               case MSGRCV:
1658                 return do_sys32_msgrcv(first, second, fifth, third, version, (void *)AA(ptr));
1659               case MSGGET:
1660                 return sys_msgget((key_t) first, second);
1661               case MSGCTL:
1662                 return msgctl32(first, second, (void *)AA(ptr));
1663
1664               case SHMAT:
1665                 return shmat32(first, second, third, version, (void *)AA(ptr));
1666                 break;
1667               case SHMDT:
1668                 return sys_shmdt((char *)AA(ptr));
1669               case SHMGET:
1670                 return sys_shmget(first, second, third);
1671               case SHMCTL:
1672                 return shmctl32(first, second, (void *)AA(ptr));
1673
1674               default:
1675                 return -ENOSYS;
1676         }
1677         return -EINVAL;
1678 }
1679
1680 /*
1681  * sys_time() can be implemented in user-level using
1682  * sys_gettimeofday().  IA64 did this but i386 Linux did not
1683  * so we have to implement this system call here.
1684  */
1685 asmlinkage long
1686 sys32_time (int *tloc)
1687 {
1688         int i;
1689
1690         /* SMP: This is fairly trivial. We grab CURRENT_TIME and
1691            stuff it to user space. No side effects */
1692         i = get_seconds();
1693         if (tloc) {
1694                 if (put_user(i, tloc))
1695                         i = -EFAULT;
1696         }
1697         return i;
1698 }
1699
1700 asmlinkage long
1701 compat_sys_wait4 (compat_pid_t pid, compat_uint_t * stat_addr, int options,
1702                  struct compat_rusage *ru);
1703
1704 asmlinkage long
1705 sys32_waitpid (int pid, unsigned int *stat_addr, int options)
1706 {
1707         return compat_sys_wait4(pid, stat_addr, options, NULL);
1708 }
1709
1710 static unsigned int
1711 ia32_peek (struct pt_regs *regs, struct task_struct *child, unsigned long addr, unsigned int *val)
1712 {
1713         size_t copied;
1714         unsigned int ret;
1715
1716         copied = access_process_vm(child, addr, val, sizeof(*val), 0);
1717         return (copied != sizeof(ret)) ? -EIO : 0;
1718 }
1719
1720 static unsigned int
1721 ia32_poke (struct pt_regs *regs, struct task_struct *child, unsigned long addr, unsigned int val)
1722 {
1723
1724         if (access_process_vm(child, addr, &val, sizeof(val), 1) != sizeof(val))
1725                 return -EIO;
1726         return 0;
1727 }
1728
1729 /*
1730  *  The order in which registers are stored in the ptrace regs structure
1731  */
1732 #define PT_EBX  0
1733 #define PT_ECX  1
1734 #define PT_EDX  2
1735 #define PT_ESI  3
1736 #define PT_EDI  4
1737 #define PT_EBP  5
1738 #define PT_EAX  6
1739 #define PT_DS   7
1740 #define PT_ES   8
1741 #define PT_FS   9
1742 #define PT_GS   10
1743 #define PT_ORIG_EAX 11
1744 #define PT_EIP  12
1745 #define PT_CS   13
1746 #define PT_EFL  14
1747 #define PT_UESP 15
1748 #define PT_SS   16
1749
1750 static unsigned int
1751 getreg (struct task_struct *child, int regno)
1752 {
1753         struct pt_regs *child_regs;
1754
1755         child_regs = ia64_task_regs(child);
1756         switch (regno / sizeof(int)) {
1757               case PT_EBX: return child_regs->r11;
1758               case PT_ECX: return child_regs->r9;
1759               case PT_EDX: return child_regs->r10;
1760               case PT_ESI: return child_regs->r14;
1761               case PT_EDI: return child_regs->r15;
1762               case PT_EBP: return child_regs->r13;
1763               case PT_EAX: return child_regs->r8;
1764               case PT_ORIG_EAX: return child_regs->r1; /* see dispatch_to_ia32_handler() */
1765               case PT_EIP: return child_regs->cr_iip;
1766               case PT_UESP: return child_regs->r12;
1767               case PT_EFL: return child->thread.eflag;
1768               case PT_DS: case PT_ES: case PT_FS: case PT_GS: case PT_SS:
1769                 return __USER_DS;
1770               case PT_CS: return __USER_CS;
1771               default:
1772                 printk(KERN_ERR "ia32.getreg(): unknown register %d\n", regno);
1773                 break;
1774         }
1775         return 0;
1776 }
1777
1778 static void
1779 putreg (struct task_struct *child, int regno, unsigned int value)
1780 {
1781         struct pt_regs *child_regs;
1782
1783         child_regs = ia64_task_regs(child);
1784         switch (regno / sizeof(int)) {
1785               case PT_EBX: child_regs->r11 = value; break;
1786               case PT_ECX: child_regs->r9 = value; break;
1787               case PT_EDX: child_regs->r10 = value; break;
1788               case PT_ESI: child_regs->r14 = value; break;
1789               case PT_EDI: child_regs->r15 = value; break;
1790               case PT_EBP: child_regs->r13 = value; break;
1791               case PT_EAX: child_regs->r8 = value; break;
1792               case PT_ORIG_EAX: child_regs->r1 = value; break;
1793               case PT_EIP: child_regs->cr_iip = value; break;
1794               case PT_UESP: child_regs->r12 = value; break;
1795               case PT_EFL: child->thread.eflag = value; break;
1796               case PT_DS: case PT_ES: case PT_FS: case PT_GS: case PT_SS:
1797                 if (value != __USER_DS)
1798                         printk(KERN_ERR
1799                                "ia32.putreg: attempt to set invalid segment register %d = %x\n",
1800                                regno, value);
1801                 break;
1802               case PT_CS:
1803                 if (value != __USER_CS)
1804                         printk(KERN_ERR
1805                                "ia32.putreg: attempt to to set invalid segment register %d = %x\n",
1806                                regno, value);
1807                 break;
1808               default:
1809                 printk(KERN_ERR "ia32.putreg: unknown register %d\n", regno);
1810                 break;
1811         }
1812 }
1813
1814 static void
1815 put_fpreg (int regno, struct _fpreg_ia32 *reg, struct pt_regs *ptp, struct switch_stack *swp,
1816            int tos)
1817 {
1818         struct _fpreg_ia32 *f;
1819         char buf[32];
1820
1821         f = (struct _fpreg_ia32 *)(((unsigned long)buf + 15) & ~15);
1822         if ((regno += tos) >= 8)
1823                 regno -= 8;
1824         switch (regno) {
1825               case 0:
1826                 ia64f2ia32f(f, &ptp->f8);
1827                 break;
1828               case 1:
1829                 ia64f2ia32f(f, &ptp->f9);
1830                 break;
1831               case 2:
1832                 ia64f2ia32f(f, &ptp->f10);
1833                 break;
1834               case 3:
1835                 ia64f2ia32f(f, &ptp->f11);
1836                 break;
1837               case 4:
1838               case 5:
1839               case 6:
1840               case 7:
1841                 ia64f2ia32f(f, &swp->f12 + (regno - 4));
1842                 break;
1843         }
1844         copy_to_user(reg, f, sizeof(*reg));
1845 }
1846
1847 static void
1848 get_fpreg (int regno, struct _fpreg_ia32 *reg, struct pt_regs *ptp, struct switch_stack *swp,
1849            int tos)
1850 {
1851
1852         if ((regno += tos) >= 8)
1853                 regno -= 8;
1854         switch (regno) {
1855               case 0:
1856                 copy_from_user(&ptp->f8, reg, sizeof(*reg));
1857                 break;
1858               case 1:
1859                 copy_from_user(&ptp->f9, reg, sizeof(*reg));
1860                 break;
1861               case 2:
1862                 copy_from_user(&ptp->f10, reg, sizeof(*reg));
1863                 break;
1864               case 3:
1865                 copy_from_user(&ptp->f11, reg, sizeof(*reg));
1866                 break;
1867               case 4:
1868               case 5:
1869               case 6:
1870               case 7:
1871                 copy_from_user(&swp->f12 + (regno - 4), reg, sizeof(*reg));
1872                 break;
1873         }
1874         return;
1875 }
1876
1877 int
1878 save_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct *save)
1879 {
1880         struct switch_stack *swp;
1881         struct pt_regs *ptp;
1882         int i, tos;
1883
1884         if (!access_ok(VERIFY_WRITE, save, sizeof(*save)))
1885                 return -EFAULT;
1886
1887         __put_user(tsk->thread.fcr & 0xffff, &save->cwd);
1888         __put_user(tsk->thread.fsr & 0xffff, &save->swd);
1889         __put_user((tsk->thread.fsr>>16) & 0xffff, &save->twd);
1890         __put_user(tsk->thread.fir, &save->fip);
1891         __put_user((tsk->thread.fir>>32) & 0xffff, &save->fcs);
1892         __put_user(tsk->thread.fdr, &save->foo);
1893         __put_user((tsk->thread.fdr>>32) & 0xffff, &save->fos);
1894
1895         /*
1896          *  Stack frames start with 16-bytes of temp space
1897          */
1898         swp = (struct switch_stack *)(tsk->thread.ksp + 16);
1899         ptp = ia64_task_regs(tsk);
1900         tos = (tsk->thread.fsr >> 11) & 7;
1901         for (i = 0; i < 8; i++)
1902                 put_fpreg(i, &save->st_space[i], ptp, swp, tos);
1903         return 0;
1904 }
1905
1906 static int
1907 restore_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct *save)
1908 {
1909         struct switch_stack *swp;
1910         struct pt_regs *ptp;
1911         int i, tos;
1912         unsigned int fsrlo, fsrhi, num32;
1913
1914         if (!access_ok(VERIFY_READ, save, sizeof(*save)))
1915                 return(-EFAULT);
1916
1917         __get_user(num32, (unsigned int *)&save->cwd);
1918         tsk->thread.fcr = (tsk->thread.fcr & (~0x1f3f)) | (num32 & 0x1f3f);
1919         __get_user(fsrlo, (unsigned int *)&save->swd);
1920         __get_user(fsrhi, (unsigned int *)&save->twd);
1921         num32 = (fsrhi << 16) | fsrlo;
1922         tsk->thread.fsr = (tsk->thread.fsr & (~0xffffffff)) | num32;
1923         __get_user(num32, (unsigned int *)&save->fip);
1924         tsk->thread.fir = (tsk->thread.fir & (~0xffffffff)) | num32;
1925         __get_user(num32, (unsigned int *)&save->foo);
1926         tsk->thread.fdr = (tsk->thread.fdr & (~0xffffffff)) | num32;
1927
1928         /*
1929          *  Stack frames start with 16-bytes of temp space
1930          */
1931         swp = (struct switch_stack *)(tsk->thread.ksp + 16);
1932         ptp = ia64_task_regs(tsk);
1933         tos = (tsk->thread.fsr >> 11) & 7;
1934         for (i = 0; i < 8; i++)
1935                 get_fpreg(i, &save->st_space[i], ptp, swp, tos);
1936         return 0;
1937 }
1938
1939 int
1940 save_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct *save)
1941 {
1942         struct switch_stack *swp;
1943         struct pt_regs *ptp;
1944         int i, tos;
1945         unsigned long mxcsr=0;
1946         unsigned long num128[2];
1947
1948         if (!access_ok(VERIFY_WRITE, save, sizeof(*save)))
1949                 return -EFAULT;
1950
1951         __put_user(tsk->thread.fcr & 0xffff, &save->cwd);
1952         __put_user(tsk->thread.fsr & 0xffff, &save->swd);
1953         __put_user((tsk->thread.fsr>>16) & 0xffff, &save->twd);
1954         __put_user(tsk->thread.fir, &save->fip);
1955         __put_user((tsk->thread.fir>>32) & 0xffff, &save->fcs);
1956         __put_user(tsk->thread.fdr, &save->foo);
1957         __put_user((tsk->thread.fdr>>32) & 0xffff, &save->fos);
1958
1959         /*
1960          *  Stack frames start with 16-bytes of temp space
1961          */
1962         swp = (struct switch_stack *)(tsk->thread.ksp + 16);
1963         ptp = ia64_task_regs(tsk);
1964         tos = (tsk->thread.fsr >> 11) & 7;
1965         for (i = 0; i < 8; i++)
1966                 put_fpreg(i, (struct _fpreg_ia32 *)&save->st_space[4*i], ptp, swp, tos);
1967
1968         mxcsr = ((tsk->thread.fcr>>32) & 0xff80) | ((tsk->thread.fsr>>32) & 0x3f);
1969         __put_user(mxcsr & 0xffff, &save->mxcsr);
1970         for (i = 0; i < 8; i++) {
1971                 memcpy(&(num128[0]), &(swp->f16) + i*2, sizeof(unsigned long));
1972                 memcpy(&(num128[1]), &(swp->f17) + i*2, sizeof(unsigned long));
1973                 copy_to_user(&save->xmm_space[0] + 4*i, num128, sizeof(struct _xmmreg_ia32));
1974         }
1975         return 0;
1976 }
1977
1978 static int
1979 restore_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct *save)
1980 {
1981         struct switch_stack *swp;
1982         struct pt_regs *ptp;
1983         int i, tos;
1984         unsigned int fsrlo, fsrhi, num32;
1985         int mxcsr;
1986         unsigned long num64;
1987         unsigned long num128[2];
1988
1989         if (!access_ok(VERIFY_READ, save, sizeof(*save)))
1990                 return(-EFAULT);
1991
1992         __get_user(num32, (unsigned int *)&save->cwd);
1993         tsk->thread.fcr = (tsk->thread.fcr & (~0x1f3f)) | (num32 & 0x1f3f);
1994         __get_user(fsrlo, (unsigned int *)&save->swd);
1995         __get_user(fsrhi, (unsigned int *)&save->twd);
1996         num32 = (fsrhi << 16) | fsrlo;
1997         tsk->thread.fsr = (tsk->thread.fsr & (~0xffffffff)) | num32;
1998         __get_user(num32, (unsigned int *)&save->fip);
1999         tsk->thread.fir = (tsk->thread.fir & (~0xffffffff)) | num32;
2000         __get_user(num32, (unsigned int *)&save->foo);
2001         tsk->thread.fdr = (tsk->thread.fdr & (~0xffffffff)) | num32;
2002
2003         /*
2004          *  Stack frames start with 16-bytes of temp space
2005          */
2006         swp = (struct switch_stack *)(tsk->thread.ksp + 16);
2007         ptp = ia64_task_regs(tsk);
2008         tos = (tsk->thread.fsr >> 11) & 7;
2009         for (i = 0; i < 8; i++)
2010         get_fpreg(i, (struct _fpreg_ia32 *)&save->st_space[4*i], ptp, swp, tos);
2011
2012         __get_user(mxcsr, (unsigned int *)&save->mxcsr);
2013         num64 = mxcsr & 0xff10;
2014         tsk->thread.fcr = (tsk->thread.fcr & (~0xff1000000000)) | (num64<<32);
2015         num64 = mxcsr & 0x3f;
2016         tsk->thread.fsr = (tsk->thread.fsr & (~0x3f00000000)) | (num64<<32);
2017
2018         for (i = 0; i < 8; i++) {
2019                 copy_from_user(num128, &save->xmm_space[0] + 4*i, sizeof(struct _xmmreg_ia32));
2020                 memcpy(&(swp->f16) + i*2, &(num128[0]), sizeof(unsigned long));
2021                 memcpy(&(swp->f17) + i*2, &(num128[1]), sizeof(unsigned long));
2022         }
2023         return 0;
2024 }
2025
2026 extern asmlinkage long sys_ptrace (long, pid_t, unsigned long, unsigned long, long, long, long,
2027                                    long, long);
2028
2029 /*
2030  *  Note that the IA32 version of `ptrace' calls the IA64 routine for
2031  *    many of the requests.  This will only work for requests that do
2032  *    not need access to the calling processes `pt_regs' which is located
2033  *    at the address of `stack'.  Once we call the IA64 `sys_ptrace' then
2034  *    the address of `stack' will not be the address of the `pt_regs'.
2035  */
2036 asmlinkage long
2037 sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data,
2038               long arg4, long arg5, long arg6, long arg7, long stack)
2039 {
2040         struct pt_regs *regs = (struct pt_regs *) &stack;
2041         struct task_struct *child;
2042         unsigned int value, tmp;
2043         long i, ret;
2044
2045         lock_kernel();
2046         if (request == PTRACE_TRACEME) {
2047                 ret = sys_ptrace(request, pid, addr, data, arg4, arg5, arg6, arg7, stack);
2048                 goto out;
2049         }
2050
2051         ret = -ESRCH;
2052         read_lock(&tasklist_lock);
2053         child = find_task_by_pid(pid);
2054         if (child)
2055                 get_task_struct(child);
2056         read_unlock(&tasklist_lock);
2057         if (!child)
2058                 goto out;
2059         ret = -EPERM;
2060         if (pid == 1)           /* no messing around with init! */
2061                 goto out_tsk;
2062
2063         if (request == PTRACE_ATTACH) {
2064                 ret = sys_ptrace(request, pid, addr, data, arg4, arg5, arg6, arg7, stack);
2065                 goto out_tsk;
2066         }
2067
2068         ret = ptrace_check_attach(child, request == PTRACE_KILL);
2069         if (ret < 0)
2070                 goto out_tsk;
2071
2072         switch (request) {
2073               case PTRACE_PEEKTEXT:
2074               case PTRACE_PEEKDATA:     /* read word at location addr */
2075                 ret = ia32_peek(regs, child, addr, &value);
2076                 if (ret == 0)
2077                         ret = put_user(value, (unsigned int *) A(data));
2078                 else
2079                         ret = -EIO;
2080                 goto out_tsk;
2081
2082               case PTRACE_POKETEXT:
2083               case PTRACE_POKEDATA:     /* write the word at location addr */
2084                 ret = ia32_poke(regs, child, addr, data);
2085                 goto out_tsk;
2086
2087               case PTRACE_PEEKUSR:      /* read word at addr in USER area */
2088                 ret = -EIO;
2089                 if ((addr & 3) || addr > 17*sizeof(int))
2090                         break;
2091
2092                 tmp = getreg(child, addr);
2093                 if (!put_user(tmp, (unsigned int *) A(data)))
2094                         ret = 0;
2095                 break;
2096
2097               case PTRACE_POKEUSR:      /* write word at addr in USER area */
2098                 ret = -EIO;
2099                 if ((addr & 3) || addr > 17*sizeof(int))
2100                         break;
2101
2102                 putreg(child, addr, data);
2103                 ret = 0;
2104                 break;
2105
2106               case IA32_PTRACE_GETREGS:
2107                 if (!access_ok(VERIFY_WRITE, (int *) A(data), 17*sizeof(int))) {
2108                         ret = -EIO;
2109                         break;
2110                 }
2111                 for (i = 0; i < (int) (17*sizeof(int)); i += sizeof(int) ) {
2112                         put_user(getreg(child, i), (unsigned int *) A(data));
2113                         data += sizeof(int);
2114                 }
2115                 ret = 0;
2116                 break;
2117
2118               case IA32_PTRACE_SETREGS:
2119                 if (!access_ok(VERIFY_READ, (int *) A(data), 17*sizeof(int))) {
2120                         ret = -EIO;
2121                         break;
2122                 }
2123                 for (i = 0; i < (int) (17*sizeof(int)); i += sizeof(int) ) {
2124                         get_user(tmp, (unsigned int *) A(data));
2125                         putreg(child, i, tmp);
2126                         data += sizeof(int);
2127                 }
2128                 ret = 0;
2129                 break;
2130
2131               case IA32_PTRACE_GETFPREGS:
2132                 ret = save_ia32_fpstate(child, (struct ia32_user_i387_struct *) A(data));
2133                 break;
2134
2135               case IA32_PTRACE_GETFPXREGS:
2136                 ret = save_ia32_fpxstate(child, (struct ia32_user_fxsr_struct *) A(data));
2137                 break;
2138
2139               case IA32_PTRACE_SETFPREGS:
2140                 ret = restore_ia32_fpstate(child, (struct ia32_user_i387_struct *) A(data));
2141                 break;
2142
2143               case IA32_PTRACE_SETFPXREGS:
2144                 ret = restore_ia32_fpxstate(child, (struct ia32_user_fxsr_struct *) A(data));
2145                 break;
2146
2147               case PTRACE_SYSCALL:      /* continue, stop after next syscall */
2148               case PTRACE_CONT:         /* restart after signal. */
2149               case PTRACE_KILL:
2150               case PTRACE_SINGLESTEP:   /* execute chile for one instruction */
2151               case PTRACE_DETACH:       /* detach a process */
2152                 ret = sys_ptrace(request, pid, addr, data, arg4, arg5, arg6, arg7, stack);
2153                 break;
2154
2155               default:
2156                 ret = ptrace_request(child, request, addr, data);
2157                 break;
2158
2159         }
2160   out_tsk:
2161         put_task_struct(child);
2162   out:
2163         unlock_kernel();
2164         return ret;
2165 }
2166
2167 /*
2168  *  The IA64 maps 4 I/O ports for each 4K page
2169  */
2170 #define IOLEN   ((65536 / 4) * 4096)
2171
2172 asmlinkage long
2173 sys32_iopl (int level)
2174 {
2175         extern unsigned long ia64_iobase;
2176         int fd;
2177         struct file * file;
2178         unsigned int old;
2179         unsigned long addr;
2180         mm_segment_t old_fs = get_fs ();
2181
2182         if (level != 3)
2183                 return(-EINVAL);
2184         /* Trying to gain more privileges? */
2185         old = ia64_getreg(_IA64_REG_AR_EFLAG);
2186         if ((unsigned int) level > ((old >> 12) & 3)) {
2187                 if (!capable(CAP_SYS_RAWIO))
2188                         return -EPERM;
2189         }
2190         set_fs(KERNEL_DS);
2191         fd = sys_open("/dev/mem", O_SYNC | O_RDWR, 0);
2192         set_fs(old_fs);
2193         if (fd < 0)
2194                 return fd;
2195         file = fget(fd);
2196         if (file == NULL) {
2197                 sys_close(fd);
2198                 return(-EFAULT);
2199         }
2200
2201         down_write(&current->mm->mmap_sem);
2202         addr = do_mmap_pgoff(file, IA32_IOBASE,
2203                              IOLEN, PROT_READ|PROT_WRITE, MAP_SHARED,
2204                              (ia64_iobase & ~PAGE_OFFSET) >> PAGE_SHIFT);
2205         up_write(&current->mm->mmap_sem);
2206
2207         if (addr >= 0) {
2208                 old = (old & ~0x3000) | (level << 12);
2209                 ia64_setreg(_IA64_REG_AR_EFLAG, old);
2210         }
2211
2212         fput(file);
2213         sys_close(fd);
2214         return 0;
2215 }
2216
2217 asmlinkage long
2218 sys32_ioperm (unsigned int from, unsigned int num, int on)
2219 {
2220
2221         /*
2222          *  Since IA64 doesn't have permission bits we'd have to go to
2223          *    a lot of trouble to simulate them in software.  There's
2224          *    no point, only trusted programs can make this call so we'll
2225          *    just turn it into an iopl call and let the process have
2226          *    access to all I/O ports.
2227          *
2228          * XXX proper ioperm() support should be emulated by
2229          *      manipulating the page protections...
2230          */
2231         return sys32_iopl(3);
2232 }
2233
2234 typedef struct {
2235         unsigned int    ss_sp;
2236         unsigned int    ss_flags;
2237         unsigned int    ss_size;
2238 } ia32_stack_t;
2239
2240 asmlinkage long
2241 sys32_sigaltstack (ia32_stack_t *uss32, ia32_stack_t *uoss32,
2242                    long arg2, long arg3, long arg4, long arg5, long arg6, long arg7, long stack)
2243 {
2244         struct pt_regs *pt = (struct pt_regs *) &stack;
2245         stack_t uss, uoss;
2246         ia32_stack_t buf32;
2247         int ret;
2248         mm_segment_t old_fs = get_fs();
2249
2250         if (uss32)
2251                 if (copy_from_user(&buf32, uss32, sizeof(ia32_stack_t)))
2252                         return -EFAULT;
2253         uss.ss_sp = (void *) (long) buf32.ss_sp;
2254         uss.ss_flags = buf32.ss_flags;
2255         /* MINSIGSTKSZ is different for ia32 vs ia64. We lie here to pass the 
2256            check and set it to the user requested value later */
2257         if ((buf32.ss_flags != SS_DISABLE) && (buf32.ss_size < MINSIGSTKSZ_IA32)) {
2258                 ret = -ENOMEM;
2259                 goto out;
2260         }
2261         uss.ss_size = MINSIGSTKSZ;
2262         set_fs(KERNEL_DS);
2263         ret = do_sigaltstack(uss32 ? &uss : NULL, &uoss, pt->r12);
2264         current->sas_ss_size = buf32.ss_size;   
2265         set_fs(old_fs);
2266 out:
2267         if (ret < 0)
2268                 return(ret);
2269         if (uoss32) {
2270                 buf32.ss_sp = (long) uoss.ss_sp;
2271                 buf32.ss_flags = uoss.ss_flags;
2272                 buf32.ss_size = uoss.ss_size;
2273                 if (copy_to_user(uoss32, &buf32, sizeof(ia32_stack_t)))
2274                         return -EFAULT;
2275         }
2276         return ret;
2277 }
2278
2279 asmlinkage int
2280 sys32_pause (void)
2281 {
2282         current->state = TASK_INTERRUPTIBLE;
2283         schedule();
2284         return -ERESTARTNOHAND;
2285 }
2286
2287 asmlinkage long sys_msync (unsigned long start, size_t len, int flags);
2288
2289 asmlinkage int
2290 sys32_msync (unsigned int start, unsigned int len, int flags)
2291 {
2292         unsigned int addr;
2293
2294         if (OFFSET4K(start))
2295                 return -EINVAL;
2296         addr = PAGE_START(start);
2297         return sys_msync(addr, len + (start - addr), flags);
2298 }
2299
2300 struct sysctl32 {
2301         unsigned int    name;
2302         int             nlen;
2303         unsigned int    oldval;
2304         unsigned int    oldlenp;
2305         unsigned int    newval;
2306         unsigned int    newlen;
2307         unsigned int    __unused[4];
2308 };
2309
2310 extern asmlinkage long sys_sysctl(struct __sysctl_args *args);
2311
2312 asmlinkage long
2313 sys32_sysctl (struct sysctl32 *args)
2314 {
2315 #ifdef CONFIG_SYSCTL
2316         struct sysctl32 a32;
2317         mm_segment_t old_fs = get_fs ();
2318         void *oldvalp, *newvalp;
2319         size_t oldlen;
2320         int *namep;
2321         long ret;
2322
2323         if (copy_from_user(&a32, args, sizeof(a32)))
2324                 return -EFAULT;
2325
2326         /*
2327          * We need to pre-validate these because we have to disable address checking
2328          * before calling do_sysctl() because of OLDLEN but we can't run the risk of the
2329          * user specifying bad addresses here.  Well, since we're dealing with 32 bit
2330          * addresses, we KNOW that access_ok() will always succeed, so this is an
2331          * expensive NOP, but so what...
2332          */
2333         namep = (int *) A(a32.name);
2334         oldvalp = (void *) A(a32.oldval);
2335         newvalp = (void *) A(a32.newval);
2336
2337         if ((oldvalp && get_user(oldlen, (int *) A(a32.oldlenp)))
2338             || !access_ok(VERIFY_WRITE, namep, 0)
2339             || !access_ok(VERIFY_WRITE, oldvalp, 0)
2340             || !access_ok(VERIFY_WRITE, newvalp, 0))
2341                 return -EFAULT;
2342
2343         set_fs(KERNEL_DS);
2344         lock_kernel();
2345         ret = do_sysctl(namep, a32.nlen, oldvalp, &oldlen, newvalp, (size_t) a32.newlen);
2346         unlock_kernel();
2347         set_fs(old_fs);
2348
2349         if (oldvalp && put_user (oldlen, (int *) A(a32.oldlenp)))
2350                 return -EFAULT;
2351
2352         return ret;
2353 #else
2354         return -ENOSYS;
2355 #endif
2356 }
2357
2358 asmlinkage long
2359 sys32_newuname (struct new_utsname *name)
2360 {
2361         extern asmlinkage long sys_newuname(struct new_utsname * name);
2362         int ret = sys_newuname(name);
2363
2364         if (!ret)
2365                 if (copy_to_user(name->machine, "i686\0\0\0", 8))
2366                         ret = -EFAULT;
2367         return ret;
2368 }
2369
2370 extern asmlinkage long sys_getresuid (uid_t *ruid, uid_t *euid, uid_t *suid);
2371
2372 asmlinkage long
2373 sys32_getresuid16 (u16 *ruid, u16 *euid, u16 *suid)
2374 {
2375         uid_t a, b, c;
2376         int ret;
2377         mm_segment_t old_fs = get_fs();
2378
2379         set_fs(KERNEL_DS);
2380         ret = sys_getresuid(&a, &b, &c);
2381         set_fs(old_fs);
2382
2383         if (put_user(a, ruid) || put_user(b, euid) || put_user(c, suid))
2384                 return -EFAULT;
2385         return ret;
2386 }
2387
2388 extern asmlinkage long sys_getresgid (gid_t *rgid, gid_t *egid, gid_t *sgid);
2389
2390 asmlinkage long
2391 sys32_getresgid16 (u16 *rgid, u16 *egid, u16 *sgid)
2392 {
2393         gid_t a, b, c;
2394         int ret;
2395         mm_segment_t old_fs = get_fs();
2396
2397         set_fs(KERNEL_DS);
2398         ret = sys_getresgid(&a, &b, &c);
2399         set_fs(old_fs);
2400
2401         if (ret)
2402                 return ret;
2403
2404         return put_user(a, rgid) | put_user(b, egid) | put_user(c, sgid);
2405 }
2406
2407 asmlinkage long
2408 sys32_lseek (unsigned int fd, int offset, unsigned int whence)
2409 {
2410         extern off_t sys_lseek (unsigned int fd, off_t offset, unsigned int origin);
2411
2412         /* Sign-extension of "offset" is important here... */
2413         return sys_lseek(fd, offset, whence);
2414 }
2415
2416 extern asmlinkage long sys_getgroups (int gidsetsize, gid_t *grouplist);
2417
2418 asmlinkage long
2419 sys32_getgroups16 (int gidsetsize, short *grouplist)
2420 {
2421         mm_segment_t old_fs = get_fs();
2422         gid_t gl[NGROUPS];
2423         int ret, i;
2424
2425         set_fs(KERNEL_DS);
2426         ret = sys_getgroups(gidsetsize, gl);
2427         set_fs(old_fs);
2428
2429         if (gidsetsize && ret > 0 && ret <= NGROUPS)
2430                 for (i = 0; i < ret; i++, grouplist++)
2431                         if (put_user(gl[i], grouplist))
2432                                 return -EFAULT;
2433         return ret;
2434 }
2435
2436 extern asmlinkage long sys_setgroups (int gidsetsize, gid_t *grouplist);
2437
2438 asmlinkage long
2439 sys32_setgroups16 (int gidsetsize, short *grouplist)
2440 {
2441         mm_segment_t old_fs = get_fs();
2442         gid_t gl[NGROUPS];
2443         int ret, i;
2444
2445         if ((unsigned) gidsetsize > NGROUPS)
2446                 return -EINVAL;
2447         for (i = 0; i < gidsetsize; i++, grouplist++)
2448                 if (get_user(gl[i], grouplist))
2449                         return -EFAULT;
2450         set_fs(KERNEL_DS);
2451         ret = sys_setgroups(gidsetsize, gl);
2452         set_fs(old_fs);
2453         return ret;
2454 }
2455
2456 asmlinkage long
2457 sys32_truncate64 (unsigned int path, unsigned int len_lo, unsigned int len_hi)
2458 {
2459         extern asmlinkage long sys_truncate (const char *path, unsigned long length);
2460
2461         return sys_truncate((const char *) A(path), ((unsigned long) len_hi << 32) | len_lo);
2462 }
2463
2464 asmlinkage long
2465 sys32_ftruncate64 (int fd, unsigned int len_lo, unsigned int len_hi)
2466 {
2467         extern asmlinkage long sys_ftruncate (int fd, unsigned long length);
2468
2469         return sys_ftruncate(fd, ((unsigned long) len_hi << 32) | len_lo);
2470 }
2471
2472 static int
2473 putstat64 (struct stat64 *ubuf, struct kstat *kbuf)
2474 {
2475         int err;
2476         u64 hdev;
2477
2478         if (clear_user(ubuf, sizeof(*ubuf)))
2479                 return -EFAULT;
2480
2481         hdev = huge_encode_dev(kbuf->dev);
2482         err  = __put_user(hdev, (u32*)&ubuf->st_dev);
2483         err |= __put_user(hdev >> 32, ((u32*)&ubuf->st_dev) + 1);
2484         err |= __put_user(kbuf->ino, &ubuf->__st_ino);
2485         err |= __put_user(kbuf->ino, &ubuf->st_ino_lo);
2486         err |= __put_user(kbuf->ino >> 32, &ubuf->st_ino_hi);
2487         err |= __put_user(kbuf->mode, &ubuf->st_mode);
2488         err |= __put_user(kbuf->nlink, &ubuf->st_nlink);
2489         err |= __put_user(kbuf->uid, &ubuf->st_uid);
2490         err |= __put_user(kbuf->gid, &ubuf->st_gid);
2491         hdev = huge_encode_dev(kbuf->rdev);
2492         err  = __put_user(hdev, (u32*)&ubuf->st_rdev);
2493         err |= __put_user(hdev >> 32, ((u32*)&ubuf->st_rdev) + 1);
2494         err |= __put_user(kbuf->size, &ubuf->st_size_lo);
2495         err |= __put_user((kbuf->size >> 32), &ubuf->st_size_hi);
2496         err |= __put_user(kbuf->atime.tv_sec, &ubuf->st_atime);
2497         err |= __put_user(kbuf->atime.tv_nsec, &ubuf->st_atime_nsec);
2498         err |= __put_user(kbuf->mtime.tv_sec, &ubuf->st_mtime);
2499         err |= __put_user(kbuf->mtime.tv_nsec, &ubuf->st_mtime_nsec);
2500         err |= __put_user(kbuf->ctime.tv_sec, &ubuf->st_ctime);
2501         err |= __put_user(kbuf->ctime.tv_nsec, &ubuf->st_ctime_nsec);
2502         err |= __put_user(kbuf->blksize, &ubuf->st_blksize);
2503         err |= __put_user(kbuf->blocks, &ubuf->st_blocks);
2504         return err;
2505 }
2506
2507 asmlinkage long
2508 sys32_stat64 (char *filename, struct stat64 *statbuf)
2509 {
2510         struct kstat s;
2511         long ret = vfs_stat(filename, &s);
2512         if (!ret)
2513                 ret = putstat64(statbuf, &s);
2514         return ret;
2515 }
2516
2517 asmlinkage long
2518 sys32_lstat64 (char *filename, struct stat64 *statbuf)
2519 {
2520         struct kstat s;
2521         long ret = vfs_lstat(filename, &s);
2522         if (!ret)
2523                 ret = putstat64(statbuf, &s);
2524         return ret;
2525 }
2526
2527 asmlinkage long
2528 sys32_fstat64 (unsigned int fd, struct stat64 *statbuf)
2529 {
2530         struct kstat s;
2531         long ret = vfs_fstat(fd, &s);
2532         if (!ret)
2533                 ret = putstat64(statbuf, &s);
2534         return ret;
2535 }
2536
2537 struct sysinfo32 {
2538         s32 uptime;
2539         u32 loads[3];
2540         u32 totalram;
2541         u32 freeram;
2542         u32 sharedram;
2543         u32 bufferram;
2544         u32 totalswap;
2545         u32 freeswap;
2546         u16 procs;
2547         u16 pad;
2548         u32 totalhigh;
2549         u32 freehigh;
2550         u32 mem_unit;
2551         char _f[8];
2552 };
2553
2554 asmlinkage long
2555 sys32_sysinfo (struct sysinfo32 *info)
2556 {
2557         extern asmlinkage long sys_sysinfo (struct sysinfo *);
2558         struct sysinfo s;
2559         long ret, err;
2560         int bitcount = 0;
2561         mm_segment_t old_fs = get_fs();
2562
2563         set_fs(KERNEL_DS);
2564         ret = sys_sysinfo(&s);
2565         set_fs(old_fs);
2566         /* Check to see if any memory value is too large for 32-bit and
2567          * scale down if needed.
2568          */
2569         if ((s.totalram >> 32) || (s.totalswap >> 32)) {
2570                 while (s.mem_unit < PAGE_SIZE) {
2571                         s.mem_unit <<= 1;
2572                         bitcount++;
2573                 }
2574                 s.totalram >>= bitcount;
2575                 s.freeram >>= bitcount;
2576                 s.sharedram >>= bitcount;
2577                 s.bufferram >>= bitcount;
2578                 s.totalswap >>= bitcount;
2579                 s.freeswap >>= bitcount;
2580                 s.totalhigh >>= bitcount;
2581                 s.freehigh >>= bitcount;
2582         }
2583
2584         if (!access_ok(VERIFY_WRITE, info, sizeof(*info)))
2585                 return -EFAULT;
2586
2587         err  = __put_user(s.uptime, &info->uptime);
2588         err |= __put_user(s.loads[0], &info->loads[0]);
2589         err |= __put_user(s.loads[1], &info->loads[1]);
2590         err |= __put_user(s.loads[2], &info->loads[2]);
2591         err |= __put_user(s.totalram, &info->totalram);
2592         err |= __put_user(s.freeram, &info->freeram);
2593         err |= __put_user(s.sharedram, &info->sharedram);
2594         err |= __put_user(s.bufferram, &info->bufferram);
2595         err |= __put_user(s.totalswap, &info->totalswap);
2596         err |= __put_user(s.freeswap, &info->freeswap);
2597         err |= __put_user(s.procs, &info->procs);
2598         err |= __put_user (s.totalhigh, &info->totalhigh);
2599         err |= __put_user (s.freehigh, &info->freehigh);
2600         err |= __put_user (s.mem_unit, &info->mem_unit);
2601         if (err)
2602                 return -EFAULT;
2603         return ret;
2604 }
2605
2606 asmlinkage long
2607 sys32_sched_rr_get_interval (pid_t pid, struct compat_timespec *interval)
2608 {
2609         extern asmlinkage long sys_sched_rr_get_interval (pid_t, struct timespec *);
2610         mm_segment_t old_fs = get_fs();
2611         struct timespec t;
2612         long ret;
2613
2614         set_fs(KERNEL_DS);
2615         ret = sys_sched_rr_get_interval(pid, &t);
2616         set_fs(old_fs);
2617         if (put_compat_timespec(&t, interval))
2618                 return -EFAULT;
2619         return ret;
2620 }
2621
2622 asmlinkage long
2623 sys32_pread (unsigned int fd, void *buf, unsigned int count, u32 pos_lo, u32 pos_hi)
2624 {
2625         extern asmlinkage long sys_pread64 (unsigned int, char *, size_t, loff_t);
2626         return sys_pread64(fd, buf, count, ((unsigned long) pos_hi << 32) | pos_lo);
2627 }
2628
2629 asmlinkage long
2630 sys32_pwrite (unsigned int fd, void *buf, unsigned int count, u32 pos_lo, u32 pos_hi)
2631 {
2632         extern asmlinkage long sys_pwrite64 (unsigned int, const char *, size_t, loff_t);
2633         return sys_pwrite64(fd, buf, count, ((unsigned long) pos_hi << 32) | pos_lo);
2634 }
2635
2636 asmlinkage long
2637 sys32_sendfile (int out_fd, int in_fd, int *offset, unsigned int count)
2638 {
2639         extern asmlinkage long sys_sendfile (int, int, off_t *, size_t);
2640         mm_segment_t old_fs = get_fs();
2641         long ret;
2642         off_t of;
2643
2644         if (offset && get_user(of, offset))
2645                 return -EFAULT;
2646
2647         set_fs(KERNEL_DS);
2648         ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
2649         set_fs(old_fs);
2650
2651         if (!ret && offset && put_user(of, offset))
2652                 return -EFAULT;
2653
2654         return ret;
2655 }
2656
2657 asmlinkage long
2658 sys32_personality (unsigned int personality)
2659 {
2660         extern asmlinkage long sys_personality (unsigned long);
2661         long ret;
2662
2663         if (current->personality == PER_LINUX32 && personality == PER_LINUX)
2664                 personality = PER_LINUX32;
2665         ret = sys_personality(personality);
2666         if (ret == PER_LINUX32)
2667                 ret = PER_LINUX;
2668         return ret;
2669 }
2670
2671 asmlinkage unsigned long
2672 sys32_brk (unsigned int brk)
2673 {
2674         unsigned long ret, obrk;
2675         struct mm_struct *mm = current->mm;
2676
2677         obrk = mm->brk;
2678         ret = sys_brk(brk);
2679         if (ret < obrk)
2680                 clear_user((void *) ret, PAGE_ALIGN(ret) - ret);
2681         return ret;
2682 }
2683
2684 /*
2685  * Exactly like fs/open.c:sys_open(), except that it doesn't set the O_LARGEFILE flag.
2686  */
2687 asmlinkage long
2688 sys32_open (const char * filename, int flags, int mode)
2689 {
2690         char * tmp;
2691         int fd, error;
2692
2693         tmp = getname(filename);
2694         fd = PTR_ERR(tmp);
2695         if (!IS_ERR(tmp)) {
2696                 fd = get_unused_fd();
2697                 if (fd >= 0) {
2698                         struct file *f = filp_open(tmp, flags, mode);
2699                         error = PTR_ERR(f);
2700                         if (IS_ERR(f))
2701                                 goto out_error;
2702                         fd_install(fd, f);
2703                 }
2704 out:
2705                 putname(tmp);
2706         }
2707         return fd;
2708
2709 out_error:
2710         put_unused_fd(fd);
2711         fd = error;
2712         goto out;
2713 }
2714
2715 /* Structure for ia32 emulation on ia64 */
2716 struct epoll_event32
2717 {
2718         u32 events;
2719         u32 data[2];
2720 }; 
2721
2722 asmlinkage long
2723 sys32_epoll_ctl(int epfd, int op, int fd, struct epoll_event32 *event)
2724 {
2725         mm_segment_t old_fs = get_fs();
2726         struct epoll_event event64;
2727         int error = -EFAULT;
2728         u32 data_halfword;
2729
2730         if ((error = verify_area(VERIFY_READ, event,
2731                                  sizeof(struct epoll_event32))))
2732                 return error;
2733
2734         __get_user(event64.events, &event->events);
2735         __get_user(data_halfword, &event->data[0]);
2736         event64.data = data_halfword;
2737         __get_user(data_halfword, &event->data[1]);
2738         event64.data |= (u64)data_halfword << 32;
2739
2740         set_fs(KERNEL_DS);
2741         error = sys_epoll_ctl(epfd, op, fd, &event64);
2742         set_fs(old_fs);
2743
2744         return error;
2745 }
2746
2747 asmlinkage long
2748 sys32_epoll_wait(int epfd, struct epoll_event32 *events, int maxevents,
2749                  int timeout)
2750 {
2751         struct epoll_event *events64 = NULL;
2752         mm_segment_t old_fs = get_fs();
2753         int error, numevents, size;
2754         int evt_idx;
2755         int do_free_pages = 0;
2756
2757         if (maxevents <= 0) {
2758                 return -EINVAL;
2759         }
2760
2761         /* Verify that the area passed by the user is writeable */
2762         if ((error = verify_area(VERIFY_WRITE, events,
2763                                  maxevents * sizeof(struct epoll_event32))))
2764                 return error;
2765
2766         /* 
2767          * Allocate space for the intermediate copy.  If the space needed 
2768          * is large enough to cause kmalloc to fail, then try again with
2769          * __get_free_pages.
2770          */
2771         size = maxevents * sizeof(struct epoll_event);
2772         events64 = kmalloc(size, GFP_KERNEL);
2773         if (events64 == NULL) {
2774                 events64 = (struct epoll_event *)
2775                                 __get_free_pages(GFP_KERNEL, get_order(size));
2776                 if (events64 == NULL) 
2777                         return -ENOMEM;
2778                 do_free_pages = 1;
2779         }
2780
2781         /* Do the system call */
2782         set_fs(KERNEL_DS); /* copy_to/from_user should work on kernel mem*/
2783         numevents = sys_epoll_wait(epfd, events64, maxevents, timeout);
2784         set_fs(old_fs);
2785
2786         /* Don't modify userspace memory if we're returning an error */
2787         if (numevents > 0) {
2788                 /* Translate the 64-bit structures back into the 32-bit
2789                    structures */
2790                 for (evt_idx = 0; evt_idx < numevents; evt_idx++) {
2791                         __put_user(events64[evt_idx].events,
2792                                    &events[evt_idx].events);
2793                         __put_user((u32)events64[evt_idx].data,
2794                                    &events[evt_idx].data[0]);
2795                         __put_user((u32)(events64[evt_idx].data >> 32),
2796                                    &events[evt_idx].data[1]);
2797                 }
2798         }
2799
2800         if (do_free_pages)
2801                 free_pages((unsigned long) events64, get_order(size));
2802         else
2803                 kfree(events64);
2804         return numevents;
2805 }
2806
2807 /*
2808  * Get a yet unused TLS descriptor index.
2809  */
2810 static int
2811 get_free_idx (void)
2812 {
2813         struct thread_struct *t = &current->thread;
2814         int idx;
2815
2816         for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++)
2817                 if (desc_empty(t->tls_array + idx))
2818                         return idx + GDT_ENTRY_TLS_MIN;
2819         return -ESRCH;
2820 }
2821
2822 /*
2823  * Set a given TLS descriptor:
2824  */
2825 asmlinkage int
2826 sys32_set_thread_area (struct ia32_user_desc *u_info)
2827 {
2828         struct thread_struct *t = &current->thread;
2829         struct ia32_user_desc info;
2830         struct desc_struct *desc;
2831         int cpu, idx;
2832
2833         if (copy_from_user(&info, u_info, sizeof(info)))
2834                 return -EFAULT;
2835         idx = info.entry_number;
2836
2837         /*
2838          * index -1 means the kernel should try to find and allocate an empty descriptor:
2839          */
2840         if (idx == -1) {
2841                 idx = get_free_idx();
2842                 if (idx < 0)
2843                         return idx;
2844                 if (put_user(idx, &u_info->entry_number))
2845                         return -EFAULT;
2846         }
2847
2848         if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
2849                 return -EINVAL;
2850
2851         desc = t->tls_array + idx - GDT_ENTRY_TLS_MIN;
2852
2853         cpu = smp_processor_id();
2854
2855         if (LDT_empty(&info)) {
2856                 desc->a = 0;
2857                 desc->b = 0;
2858         } else {
2859                 desc->a = LDT_entry_a(&info);
2860                 desc->b = LDT_entry_b(&info);
2861         }
2862         load_TLS(t, cpu);
2863         return 0;
2864 }
2865
2866 /*
2867  * Get the current Thread-Local Storage area:
2868  */
2869
2870 #define GET_BASE(desc) (                        \
2871         (((desc)->a >> 16) & 0x0000ffff) |      \
2872         (((desc)->b << 16) & 0x00ff0000) |      \
2873         ( (desc)->b        & 0xff000000)   )
2874
2875 #define GET_LIMIT(desc) (                       \
2876         ((desc)->a & 0x0ffff) |                 \
2877          ((desc)->b & 0xf0000) )
2878
2879 #define GET_32BIT(desc)         (((desc)->b >> 23) & 1)
2880 #define GET_CONTENTS(desc)      (((desc)->b >> 10) & 3)
2881 #define GET_WRITABLE(desc)      (((desc)->b >>  9) & 1)
2882 #define GET_LIMIT_PAGES(desc)   (((desc)->b >> 23) & 1)
2883 #define GET_PRESENT(desc)       (((desc)->b >> 15) & 1)
2884 #define GET_USEABLE(desc)       (((desc)->b >> 20) & 1)
2885
2886 asmlinkage int
2887 sys32_get_thread_area (struct ia32_user_desc *u_info)
2888 {
2889         struct ia32_user_desc info;
2890         struct desc_struct *desc;
2891         int idx;
2892
2893         if (get_user(idx, &u_info->entry_number))
2894                 return -EFAULT;
2895         if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
2896                 return -EINVAL;
2897
2898         desc = current->thread.tls_array + idx - GDT_ENTRY_TLS_MIN;
2899
2900         info.entry_number = idx;
2901         info.base_addr = GET_BASE(desc);
2902         info.limit = GET_LIMIT(desc);
2903         info.seg_32bit = GET_32BIT(desc);
2904         info.contents = GET_CONTENTS(desc);
2905         info.read_exec_only = !GET_WRITABLE(desc);
2906         info.limit_in_pages = GET_LIMIT_PAGES(desc);
2907         info.seg_not_present = !GET_PRESENT(desc);
2908         info.useable = GET_USEABLE(desc);
2909
2910         if (copy_to_user(u_info, &info, sizeof(info)))
2911                 return -EFAULT;
2912         return 0;
2913 }
2914
2915 extern asmlinkage long
2916 sys_timer_create(clockid_t which_clock, struct sigevent *timer_event_spec,
2917                  timer_t * created_timer_id);
2918
2919 asmlinkage long
2920 sys32_timer_create(u32 clock, struct sigevent32 *se32, timer_t *timer_id)
2921 {
2922         struct sigevent se;
2923         mm_segment_t oldfs;
2924         timer_t t;
2925         long err;
2926
2927         if (se32 == NULL)
2928                 return sys_timer_create(clock, NULL, timer_id);
2929
2930         memset(&se, 0, sizeof(struct sigevent));
2931         if (get_user(se.sigev_value.sival_int,  &se32->sigev_value.sival_int) ||
2932             __get_user(se.sigev_signo, &se32->sigev_signo) ||
2933             __get_user(se.sigev_notify, &se32->sigev_notify) ||
2934             __copy_from_user(&se._sigev_un._pad, &se32->_sigev_un._pad,
2935             sizeof(se._sigev_un._pad)))
2936                 return -EFAULT;
2937
2938         if (!access_ok(VERIFY_WRITE,timer_id,sizeof(timer_t)))
2939                 return -EFAULT;
2940
2941         oldfs = get_fs();
2942         set_fs(KERNEL_DS);
2943         err = sys_timer_create(clock, &se, &t);
2944         set_fs(oldfs);
2945
2946         if (!err)
2947                 err = __put_user (t, timer_id);
2948
2949         return err;
2950 }
2951
2952 extern long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice);
2953
2954 long sys32_fadvise64_64(int fd, __u32 offset_low, __u32 offset_high, 
2955                         __u32 len_low, __u32 len_high, int advice)
2956
2957         return sys_fadvise64_64(fd,
2958                                (((u64)offset_high)<<32) | offset_low,
2959                                (((u64)len_high)<<32) | len_low,
2960                                advice); 
2961
2962
2963 #ifdef  NOTYET  /* UNTESTED FOR IA64 FROM HERE DOWN */
2964
2965 struct ncp_mount_data32 {
2966         int version;
2967         unsigned int ncp_fd;
2968         compat_uid_t mounted_uid;
2969         int wdog_pid;
2970         unsigned char mounted_vol[NCP_VOLNAME_LEN + 1];
2971         unsigned int time_out;
2972         unsigned int retry_count;
2973         unsigned int flags;
2974         compat_uid_t uid;
2975         compat_gid_t gid;
2976         compat_mode_t file_mode;
2977         compat_mode_t dir_mode;
2978 };
2979
2980 static void *
2981 do_ncp_super_data_conv(void *raw_data)
2982 {
2983         struct ncp_mount_data *n = (struct ncp_mount_data *)raw_data;
2984         struct ncp_mount_data32 *n32 = (struct ncp_mount_data32 *)raw_data;
2985
2986         n->dir_mode = n32->dir_mode;
2987         n->file_mode = n32->file_mode;
2988         n->gid = n32->gid;
2989         n->uid = n32->uid;
2990         memmove (n->mounted_vol, n32->mounted_vol,
2991                  (sizeof (n32->mounted_vol) + 3 * sizeof (unsigned int)));
2992         n->wdog_pid = n32->wdog_pid;
2993         n->mounted_uid = n32->mounted_uid;
2994         return raw_data;
2995 }
2996
2997 struct smb_mount_data32 {
2998         int version;
2999         compat_uid_t mounted_uid;
3000         compat_uid_t uid;
3001         compat_gid_t gid;
3002         compat_mode_t file_mode;
3003         compat_mode_t dir_mode;
3004 };
3005
3006 static void *
3007 do_smb_super_data_conv(void *raw_data)
3008 {
3009         struct smb_mount_data *s = (struct smb_mount_data *)raw_data;
3010         struct smb_mount_data32 *s32 = (struct smb_mount_data32 *)raw_data;
3011
3012         if (s32->version != SMB_MOUNT_OLDVERSION)
3013                 goto out;
3014         s->version = s32->version;
3015         s->mounted_uid = s32->mounted_uid;
3016         s->uid = s32->uid;
3017         s->gid = s32->gid;
3018         s->file_mode = s32->file_mode;
3019         s->dir_mode = s32->dir_mode;
3020 out:
3021         return raw_data;
3022 }
3023
3024 static int
3025 copy_mount_stuff_to_kernel(const void *user, unsigned long *kernel)
3026 {
3027         int i;
3028         unsigned long page;
3029         struct vm_area_struct *vma;
3030
3031         *kernel = 0;
3032         if(!user)
3033                 return 0;
3034         vma = find_vma(current->mm, (unsigned long)user);
3035         if(!vma || (unsigned long)user < vma->vm_start)
3036                 return -EFAULT;
3037         if(!(vma->vm_flags & VM_READ))
3038                 return -EFAULT;
3039         i = vma->vm_end - (unsigned long) user;
3040         if(PAGE_SIZE <= (unsigned long) i)
3041                 i = PAGE_SIZE - 1;
3042         if(!(page = __get_free_page(GFP_KERNEL)))
3043                 return -ENOMEM;
3044         if(copy_from_user((void *) page, user, i)) {
3045                 free_page(page);
3046                 return -EFAULT;
3047         }
3048         *kernel = page;
3049         return 0;
3050 }
3051
3052 extern asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type,
3053                                 unsigned long new_flags, void *data);
3054
3055 #define SMBFS_NAME      "smbfs"
3056 #define NCPFS_NAME      "ncpfs"
3057
3058 asmlinkage long
3059 sys32_mount(char *dev_name, char *dir_name, char *type,
3060             unsigned long new_flags, u32 data)
3061 {
3062         unsigned long type_page;
3063         int err, is_smb, is_ncp;
3064
3065         if(!capable(CAP_SYS_ADMIN))
3066                 return -EPERM;
3067         is_smb = is_ncp = 0;
3068         err = copy_mount_stuff_to_kernel((const void *)type, &type_page);
3069         if(err)
3070                 return err;
3071         if(type_page) {
3072                 is_smb = !strcmp((char *)type_page, SMBFS_NAME);
3073                 is_ncp = !strcmp((char *)type_page, NCPFS_NAME);
3074         }
3075         if(!is_smb && !is_ncp) {
3076                 if(type_page)
3077                         free_page(type_page);
3078                 return sys_mount(dev_name, dir_name, type, new_flags,
3079                                  (void *)AA(data));
3080         } else {
3081                 unsigned long dev_page, dir_page, data_page;
3082
3083                 err = copy_mount_stuff_to_kernel((const void *)dev_name,
3084                                                  &dev_page);
3085                 if(err)
3086                         goto out;
3087                 err = copy_mount_stuff_to_kernel((const void *)dir_name,
3088                                                  &dir_page);
3089                 if(err)
3090                         goto dev_out;
3091                 err = copy_mount_stuff_to_kernel((const void *)AA(data),
3092                                                  &data_page);
3093                 if(err)
3094                         goto dir_out;
3095                 if(is_ncp)
3096                         do_ncp_super_data_conv((void *)data_page);
3097                 else if(is_smb)
3098                         do_smb_super_data_conv((void *)data_page);
3099                 else
3100                         panic("The problem is here...");
3101                 err = do_mount((char *)dev_page, (char *)dir_page,
3102                                 (char *)type_page, new_flags,
3103                                 (void *)data_page);
3104                 if(data_page)
3105                         free_page(data_page);
3106         dir_out:
3107                 if(dir_page)
3108                         free_page(dir_page);
3109         dev_out:
3110                 if(dev_page)
3111                         free_page(dev_page);
3112         out:
3113                 if(type_page)
3114                         free_page(type_page);
3115                 return err;
3116         }
3117 }
3118
3119 extern asmlinkage long sys_setreuid(uid_t ruid, uid_t euid);
3120
3121 asmlinkage long sys32_setreuid(compat_uid_t ruid, compat_uid_t euid)
3122 {
3123         uid_t sruid, seuid;
3124
3125         sruid = (ruid == (compat_uid_t)-1) ? ((uid_t)-1) : ((uid_t)ruid);
3126         seuid = (euid == (compat_uid_t)-1) ? ((uid_t)-1) : ((uid_t)euid);
3127         return sys_setreuid(sruid, seuid);
3128 }
3129
3130 extern asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid);
3131
3132 asmlinkage long
3133 sys32_setresuid(compat_uid_t ruid, compat_uid_t euid,
3134                 compat_uid_t suid)
3135 {
3136         uid_t sruid, seuid, ssuid;
3137
3138         sruid = (ruid == (compat_uid_t)-1) ? ((uid_t)-1) : ((uid_t)ruid);
3139         seuid = (euid == (compat_uid_t)-1) ? ((uid_t)-1) : ((uid_t)euid);
3140         ssuid = (suid == (compat_uid_t)-1) ? ((uid_t)-1) : ((uid_t)suid);
3141         return sys_setresuid(sruid, seuid, ssuid);
3142 }
3143
3144 extern asmlinkage long sys_setregid(gid_t rgid, gid_t egid);
3145
3146 asmlinkage long
3147 sys32_setregid(compat_gid_t rgid, compat_gid_t egid)
3148 {
3149         gid_t srgid, segid;
3150
3151         srgid = (rgid == (compat_gid_t)-1) ? ((gid_t)-1) : ((gid_t)rgid);
3152         segid = (egid == (compat_gid_t)-1) ? ((gid_t)-1) : ((gid_t)egid);
3153         return sys_setregid(srgid, segid);
3154 }
3155
3156 extern asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid);
3157
3158 asmlinkage long
3159 sys32_setresgid(compat_gid_t rgid, compat_gid_t egid,
3160                 compat_gid_t sgid)
3161 {
3162         gid_t srgid, segid, ssgid;
3163
3164         srgid = (rgid == (compat_gid_t)-1) ? ((gid_t)-1) : ((gid_t)rgid);
3165         segid = (egid == (compat_gid_t)-1) ? ((gid_t)-1) : ((gid_t)egid);
3166         ssgid = (sgid == (compat_gid_t)-1) ? ((gid_t)-1) : ((gid_t)sgid);
3167         return sys_setresgid(srgid, segid, ssgid);
3168 }
3169
3170 /* Stuff for NFS server syscalls... */
3171 struct nfsctl_svc32 {
3172         u16                     svc32_port;
3173         s32                     svc32_nthreads;
3174 };
3175
3176 struct nfsctl_client32 {
3177         s8                      cl32_ident[NFSCLNT_IDMAX+1];
3178         s32                     cl32_naddr;
3179         struct in_addr          cl32_addrlist[NFSCLNT_ADDRMAX];
3180         s32                     cl32_fhkeytype;
3181         s32                     cl32_fhkeylen;
3182         u8                      cl32_fhkey[NFSCLNT_KEYMAX];
3183 };
3184
3185 struct nfsctl_export32 {
3186         s8                      ex32_client[NFSCLNT_IDMAX+1];
3187         s8                      ex32_path[NFS_MAXPATHLEN+1];
3188         compat_dev_t    ex32_dev;
3189         compat_ino_t    ex32_ino;
3190         s32                     ex32_flags;
3191         compat_uid_t    ex32_anon_uid;
3192         compat_gid_t    ex32_anon_gid;
3193 };
3194
3195 struct nfsctl_arg32 {
3196         s32                     ca32_version;   /* safeguard */
3197         union {
3198                 struct nfsctl_svc32     u32_svc;
3199                 struct nfsctl_client32  u32_client;
3200                 struct nfsctl_export32  u32_export;
3201                 u32                     u32_debug;
3202         } u;
3203 #define ca32_svc        u.u32_svc
3204 #define ca32_client     u.u32_client
3205 #define ca32_export     u.u32_export
3206 #define ca32_debug      u.u32_debug
3207 };
3208
3209 union nfsctl_res32 {
3210         struct knfs_fh          cr32_getfh;
3211         u32                     cr32_debug;
3212 };
3213
3214 static int
3215 nfs_svc32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3216 {
3217         int err;
3218
3219         err = __get_user(karg->ca_version, &arg32->ca32_version);
3220         err |= __get_user(karg->ca_svc.svc_port, &arg32->ca32_svc.svc32_port);
3221         err |= __get_user(karg->ca_svc.svc_nthreads,
3222                           &arg32->ca32_svc.svc32_nthreads);
3223         return err;
3224 }
3225
3226 static int
3227 nfs_clnt32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3228 {
3229         int err;
3230
3231         err = __get_user(karg->ca_version, &arg32->ca32_version);
3232         err |= copy_from_user(&karg->ca_client.cl_ident[0],
3233                           &arg32->ca32_client.cl32_ident[0],
3234                           NFSCLNT_IDMAX);
3235         err |= __get_user(karg->ca_client.cl_naddr,
3236                           &arg32->ca32_client.cl32_naddr);
3237         err |= copy_from_user(&karg->ca_client.cl_addrlist[0],
3238                           &arg32->ca32_client.cl32_addrlist[0],
3239                           (sizeof(struct in_addr) * NFSCLNT_ADDRMAX));
3240         err |= __get_user(karg->ca_client.cl_fhkeytype,
3241                       &arg32->ca32_client.cl32_fhkeytype);
3242         err |= __get_user(karg->ca_client.cl_fhkeylen,
3243                       &arg32->ca32_client.cl32_fhkeylen);
3244         err |= copy_from_user(&karg->ca_client.cl_fhkey[0],
3245                           &arg32->ca32_client.cl32_fhkey[0],
3246                           NFSCLNT_KEYMAX);
3247         return err;
3248 }
3249
3250 static int
3251 nfs_exp32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3252 {
3253         int err;
3254
3255         err = __get_user(karg->ca_version, &arg32->ca32_version);
3256         err |= copy_from_user(&karg->ca_export.ex_client[0],
3257                           &arg32->ca32_export.ex32_client[0],
3258                           NFSCLNT_IDMAX);
3259         err |= copy_from_user(&karg->ca_export.ex_path[0],
3260                           &arg32->ca32_export.ex32_path[0],
3261                           NFS_MAXPATHLEN);
3262         err |= __get_user(karg->ca_export.ex_dev,
3263                       &arg32->ca32_export.ex32_dev);
3264         err |= __get_user(karg->ca_export.ex_ino,
3265                       &arg32->ca32_export.ex32_ino);
3266         err |= __get_user(karg->ca_export.ex_flags,
3267                       &arg32->ca32_export.ex32_flags);
3268         err |= __get_user(karg->ca_export.ex_anon_uid,
3269                       &arg32->ca32_export.ex32_anon_uid);
3270         err |= __get_user(karg->ca_export.ex_anon_gid,
3271                       &arg32->ca32_export.ex32_anon_gid);
3272         return err;
3273 }
3274
3275 static int
3276 nfs_getfh32_res_trans(union nfsctl_res *kres, union nfsctl_res32 *res32)
3277 {
3278         int err;
3279
3280         err = copy_to_user(&res32->cr32_getfh,
3281                         &kres->cr_getfh,
3282                         sizeof(res32->cr32_getfh));
3283         err |= __put_user(kres->cr_debug, &res32->cr32_debug);
3284         return err;
3285 }
3286
3287 extern asmlinkage long sys_nfsservctl(int cmd, void *arg, void *resp);
3288
3289 int asmlinkage
3290 sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsctl_res32 *res32)
3291 {
3292         struct nfsctl_arg *karg = NULL;
3293         union nfsctl_res *kres = NULL;
3294         mm_segment_t oldfs;
3295         int err;
3296
3297         karg = kmalloc(sizeof(*karg), GFP_USER);
3298         if(!karg)
3299                 return -ENOMEM;
3300         if(res32) {
3301                 kres = kmalloc(sizeof(*kres), GFP_USER);
3302                 if(!kres) {
3303                         kfree(karg);
3304                         return -ENOMEM;
3305                 }
3306         }
3307         switch(cmd) {
3308         case NFSCTL_SVC:
3309                 err = nfs_svc32_trans(karg, arg32);
3310                 break;
3311         case NFSCTL_ADDCLIENT:
3312                 err = nfs_clnt32_trans(karg, arg32);
3313                 break;
3314         case NFSCTL_DELCLIENT:
3315                 err = nfs_clnt32_trans(karg, arg32);
3316                 break;
3317         case NFSCTL_EXPORT:
3318                 err = nfs_exp32_trans(karg, arg32);
3319                 break;
3320         default:
3321                 err = -EINVAL;
3322                 break;
3323         }
3324         if(err)
3325                 goto done;
3326         oldfs = get_fs();
3327         set_fs(KERNEL_DS);
3328         err = sys_nfsservctl(cmd, karg, kres);
3329         set_fs(oldfs);
3330
3331         if(!err && cmd == NFSCTL_GETFS)
3332                 err = nfs_getfh32_res_trans(kres, res32);
3333
3334 done:
3335         if(karg)
3336                 kfree(karg);
3337         if(kres)
3338                 kfree(kres);
3339         return err;
3340 }
3341
3342 /* Handle adjtimex compatibility. */
3343
3344 struct timex32 {
3345         u32 modes;
3346         s32 offset, freq, maxerror, esterror;
3347         s32 status, constant, precision, tolerance;
3348         struct compat_timeval time;
3349         s32 tick;
3350         s32 ppsfreq, jitter, shift, stabil;
3351         s32 jitcnt, calcnt, errcnt, stbcnt;
3352         s32  :32; s32  :32; s32  :32; s32  :32;
3353         s32  :32; s32  :32; s32  :32; s32  :32;
3354         s32  :32; s32  :32; s32  :32; s32  :32;
3355 };
3356
3357 extern int do_adjtimex(struct timex *);
3358
3359 asmlinkage long
3360 sys32_adjtimex(struct timex32 *utp)
3361 {
3362         struct timex txc;
3363         int ret;
3364
3365         memset(&txc, 0, sizeof(struct timex));
3366
3367         if(get_user(txc.modes, &utp->modes) ||
3368            __get_user(txc.offset, &utp->offset) ||
3369            __get_user(txc.freq, &utp->freq) ||
3370            __get_user(txc.maxerror, &utp->maxerror) ||
3371            __get_user(txc.esterror, &utp->esterror) ||
3372            __get_user(txc.status, &utp->status) ||
3373            __get_user(txc.constant, &utp->constant) ||
3374            __get_user(txc.precision, &utp->precision) ||
3375            __get_user(txc.tolerance, &utp->tolerance) ||
3376            __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
3377            __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
3378            __get_user(txc.tick, &utp->tick) ||
3379            __get_user(txc.ppsfreq, &utp->ppsfreq) ||
3380            __get_user(txc.jitter, &utp->jitter) ||
3381            __get_user(txc.shift, &utp->shift) ||
3382            __get_user(txc.stabil, &utp->stabil) ||
3383            __get_user(txc.jitcnt, &utp->jitcnt) ||
3384            __get_user(txc.calcnt, &utp->calcnt) ||
3385            __get_user(txc.errcnt, &utp->errcnt) ||
3386            __get_user(txc.stbcnt, &utp->stbcnt))
3387                 return -EFAULT;
3388
3389         ret = do_adjtimex(&txc);
3390
3391         if(put_user(txc.modes, &utp->modes) ||
3392            __put_user(txc.offset, &utp->offset) ||
3393            __put_user(txc.freq, &utp->freq) ||
3394            __put_user(txc.maxerror, &utp->maxerror) ||
3395            __put_user(txc.esterror, &utp->esterror) ||
3396            __put_user(txc.status, &utp->status) ||
3397            __put_user(txc.constant, &utp->constant) ||
3398            __put_user(txc.precision, &utp->precision) ||
3399            __put_user(txc.tolerance, &utp->tolerance) ||
3400            __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
3401            __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
3402            __put_user(txc.tick, &utp->tick) ||
3403            __put_user(txc.ppsfreq, &utp->ppsfreq) ||
3404            __put_user(txc.jitter, &utp->jitter) ||
3405            __put_user(txc.shift, &utp->shift) ||
3406            __put_user(txc.stabil, &utp->stabil) ||
3407            __put_user(txc.jitcnt, &utp->jitcnt) ||
3408            __put_user(txc.calcnt, &utp->calcnt) ||
3409            __put_user(txc.errcnt, &utp->errcnt) ||
3410            __put_user(txc.stbcnt, &utp->stbcnt))
3411                 ret = -EFAULT;
3412
3413         return ret;
3414 }
3415 #endif /* NOTYET */