+- add patches.fixes/linux-post-2.6.3-20040220
[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 static int
2417 groups16_to_user(short *grouplist, struct group_info *group_info)
2418 {
2419         int i;
2420         short group;
2421
2422         for (i = 0; i < group_info->ngroups; i++) {
2423                 group = (short)GROUP_AT(group_info, i);
2424                 if (put_user(group, grouplist+i))
2425                         return -EFAULT;
2426         }
2427
2428         return 0;
2429 }
2430
2431 static int
2432 groups16_from_user(struct group_info *group_info, short *grouplist)
2433 {
2434         int i;
2435         short group;
2436
2437         for (i = 0; i < group_info->ngroups; i++) {
2438                 if (get_user(group, grouplist+i))
2439                         return  -EFAULT;
2440                 GROUP_AT(group_info, i) = (gid_t)group;
2441         }
2442
2443         return 0;
2444 }
2445
2446 asmlinkage long
2447 sys32_getgroups16 (int gidsetsize, short *grouplist)
2448 {
2449         int i;
2450
2451         if (gidsetsize < 0)
2452                 return -EINVAL;
2453
2454         get_group_info(current->group_info);
2455         i = current->group_info->ngroups;
2456         if (gidsetsize) {
2457                 if (i > gidsetsize) {
2458                         i = -EINVAL;
2459                         goto out;
2460                 }
2461                 if (groups16_to_user(grouplist, current->group_info)) {
2462                         i = -EFAULT;
2463                         goto out;
2464                 }
2465         }
2466 out:
2467         put_group_info(current->group_info);
2468         return i;
2469 }
2470
2471 asmlinkage long
2472 sys32_setgroups16 (int gidsetsize, short *grouplist)
2473 {
2474         struct group_info *group_info;
2475         int retval;
2476
2477         if (!capable(CAP_SETGID))
2478                 return -EPERM;
2479         if ((unsigned)gidsetsize > NGROUPS_MAX)
2480                 return -EINVAL;
2481
2482         group_info = groups_alloc(gidsetsize);
2483         if (!group_info)
2484                 return -ENOMEM;
2485         retval = groups16_from_user(group_info, grouplist);
2486         if (retval) {
2487                 put_group_info(group_info);
2488                 return retval;
2489         }
2490
2491         retval = set_current_groups(group_info);
2492         put_group_info(group_info);
2493
2494         return retval;
2495 }
2496
2497 asmlinkage long
2498 sys32_truncate64 (unsigned int path, unsigned int len_lo, unsigned int len_hi)
2499 {
2500         extern asmlinkage long sys_truncate (const char *path, unsigned long length);
2501
2502         return sys_truncate((const char *) A(path), ((unsigned long) len_hi << 32) | len_lo);
2503 }
2504
2505 asmlinkage long
2506 sys32_ftruncate64 (int fd, unsigned int len_lo, unsigned int len_hi)
2507 {
2508         extern asmlinkage long sys_ftruncate (int fd, unsigned long length);
2509
2510         return sys_ftruncate(fd, ((unsigned long) len_hi << 32) | len_lo);
2511 }
2512
2513 static int
2514 putstat64 (struct stat64 *ubuf, struct kstat *kbuf)
2515 {
2516         int err;
2517         u64 hdev;
2518
2519         if (clear_user(ubuf, sizeof(*ubuf)))
2520                 return -EFAULT;
2521
2522         hdev = huge_encode_dev(kbuf->dev);
2523         err  = __put_user(hdev, (u32*)&ubuf->st_dev);
2524         err |= __put_user(hdev >> 32, ((u32*)&ubuf->st_dev) + 1);
2525         err |= __put_user(kbuf->ino, &ubuf->__st_ino);
2526         err |= __put_user(kbuf->ino, &ubuf->st_ino_lo);
2527         err |= __put_user(kbuf->ino >> 32, &ubuf->st_ino_hi);
2528         err |= __put_user(kbuf->mode, &ubuf->st_mode);
2529         err |= __put_user(kbuf->nlink, &ubuf->st_nlink);
2530         err |= __put_user(kbuf->uid, &ubuf->st_uid);
2531         err |= __put_user(kbuf->gid, &ubuf->st_gid);
2532         hdev = huge_encode_dev(kbuf->rdev);
2533         err  = __put_user(hdev, (u32*)&ubuf->st_rdev);
2534         err |= __put_user(hdev >> 32, ((u32*)&ubuf->st_rdev) + 1);
2535         err |= __put_user(kbuf->size, &ubuf->st_size_lo);
2536         err |= __put_user((kbuf->size >> 32), &ubuf->st_size_hi);
2537         err |= __put_user(kbuf->atime.tv_sec, &ubuf->st_atime);
2538         err |= __put_user(kbuf->atime.tv_nsec, &ubuf->st_atime_nsec);
2539         err |= __put_user(kbuf->mtime.tv_sec, &ubuf->st_mtime);
2540         err |= __put_user(kbuf->mtime.tv_nsec, &ubuf->st_mtime_nsec);
2541         err |= __put_user(kbuf->ctime.tv_sec, &ubuf->st_ctime);
2542         err |= __put_user(kbuf->ctime.tv_nsec, &ubuf->st_ctime_nsec);
2543         err |= __put_user(kbuf->blksize, &ubuf->st_blksize);
2544         err |= __put_user(kbuf->blocks, &ubuf->st_blocks);
2545         return err;
2546 }
2547
2548 asmlinkage long
2549 sys32_stat64 (char *filename, struct stat64 *statbuf)
2550 {
2551         struct kstat s;
2552         long ret = vfs_stat(filename, &s);
2553         if (!ret)
2554                 ret = putstat64(statbuf, &s);
2555         return ret;
2556 }
2557
2558 asmlinkage long
2559 sys32_lstat64 (char *filename, struct stat64 *statbuf)
2560 {
2561         struct kstat s;
2562         long ret = vfs_lstat(filename, &s);
2563         if (!ret)
2564                 ret = putstat64(statbuf, &s);
2565         return ret;
2566 }
2567
2568 asmlinkage long
2569 sys32_fstat64 (unsigned int fd, struct stat64 *statbuf)
2570 {
2571         struct kstat s;
2572         long ret = vfs_fstat(fd, &s);
2573         if (!ret)
2574                 ret = putstat64(statbuf, &s);
2575         return ret;
2576 }
2577
2578 struct sysinfo32 {
2579         s32 uptime;
2580         u32 loads[3];
2581         u32 totalram;
2582         u32 freeram;
2583         u32 sharedram;
2584         u32 bufferram;
2585         u32 totalswap;
2586         u32 freeswap;
2587         u16 procs;
2588         u16 pad;
2589         u32 totalhigh;
2590         u32 freehigh;
2591         u32 mem_unit;
2592         char _f[8];
2593 };
2594
2595 asmlinkage long
2596 sys32_sysinfo (struct sysinfo32 *info)
2597 {
2598         extern asmlinkage long sys_sysinfo (struct sysinfo *);
2599         struct sysinfo s;
2600         long ret, err;
2601         int bitcount = 0;
2602         mm_segment_t old_fs = get_fs();
2603
2604         set_fs(KERNEL_DS);
2605         ret = sys_sysinfo(&s);
2606         set_fs(old_fs);
2607         /* Check to see if any memory value is too large for 32-bit and
2608          * scale down if needed.
2609          */
2610         if ((s.totalram >> 32) || (s.totalswap >> 32)) {
2611                 while (s.mem_unit < PAGE_SIZE) {
2612                         s.mem_unit <<= 1;
2613                         bitcount++;
2614                 }
2615                 s.totalram >>= bitcount;
2616                 s.freeram >>= bitcount;
2617                 s.sharedram >>= bitcount;
2618                 s.bufferram >>= bitcount;
2619                 s.totalswap >>= bitcount;
2620                 s.freeswap >>= bitcount;
2621                 s.totalhigh >>= bitcount;
2622                 s.freehigh >>= bitcount;
2623         }
2624
2625         if (!access_ok(VERIFY_WRITE, info, sizeof(*info)))
2626                 return -EFAULT;
2627
2628         err  = __put_user(s.uptime, &info->uptime);
2629         err |= __put_user(s.loads[0], &info->loads[0]);
2630         err |= __put_user(s.loads[1], &info->loads[1]);
2631         err |= __put_user(s.loads[2], &info->loads[2]);
2632         err |= __put_user(s.totalram, &info->totalram);
2633         err |= __put_user(s.freeram, &info->freeram);
2634         err |= __put_user(s.sharedram, &info->sharedram);
2635         err |= __put_user(s.bufferram, &info->bufferram);
2636         err |= __put_user(s.totalswap, &info->totalswap);
2637         err |= __put_user(s.freeswap, &info->freeswap);
2638         err |= __put_user(s.procs, &info->procs);
2639         err |= __put_user (s.totalhigh, &info->totalhigh);
2640         err |= __put_user (s.freehigh, &info->freehigh);
2641         err |= __put_user (s.mem_unit, &info->mem_unit);
2642         if (err)
2643                 return -EFAULT;
2644         return ret;
2645 }
2646
2647 asmlinkage long
2648 sys32_sched_rr_get_interval (pid_t pid, struct compat_timespec *interval)
2649 {
2650         extern asmlinkage long sys_sched_rr_get_interval (pid_t, struct timespec *);
2651         mm_segment_t old_fs = get_fs();
2652         struct timespec t;
2653         long ret;
2654
2655         set_fs(KERNEL_DS);
2656         ret = sys_sched_rr_get_interval(pid, &t);
2657         set_fs(old_fs);
2658         if (put_compat_timespec(&t, interval))
2659                 return -EFAULT;
2660         return ret;
2661 }
2662
2663 asmlinkage long
2664 sys32_pread (unsigned int fd, void *buf, unsigned int count, u32 pos_lo, u32 pos_hi)
2665 {
2666         extern asmlinkage long sys_pread64 (unsigned int, char *, size_t, loff_t);
2667         return sys_pread64(fd, buf, count, ((unsigned long) pos_hi << 32) | pos_lo);
2668 }
2669
2670 asmlinkage long
2671 sys32_pwrite (unsigned int fd, void *buf, unsigned int count, u32 pos_lo, u32 pos_hi)
2672 {
2673         extern asmlinkage long sys_pwrite64 (unsigned int, const char *, size_t, loff_t);
2674         return sys_pwrite64(fd, buf, count, ((unsigned long) pos_hi << 32) | pos_lo);
2675 }
2676
2677 asmlinkage long
2678 sys32_sendfile (int out_fd, int in_fd, int *offset, unsigned int count)
2679 {
2680         extern asmlinkage long sys_sendfile (int, int, off_t *, size_t);
2681         mm_segment_t old_fs = get_fs();
2682         long ret;
2683         off_t of;
2684
2685         if (offset && get_user(of, offset))
2686                 return -EFAULT;
2687
2688         set_fs(KERNEL_DS);
2689         ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
2690         set_fs(old_fs);
2691
2692         if (!ret && offset && put_user(of, offset))
2693                 return -EFAULT;
2694
2695         return ret;
2696 }
2697
2698 asmlinkage long
2699 sys32_personality (unsigned int personality)
2700 {
2701         extern asmlinkage long sys_personality (unsigned long);
2702         long ret;
2703
2704         if (current->personality == PER_LINUX32 && personality == PER_LINUX)
2705                 personality = PER_LINUX32;
2706         ret = sys_personality(personality);
2707         if (ret == PER_LINUX32)
2708                 ret = PER_LINUX;
2709         return ret;
2710 }
2711
2712 asmlinkage unsigned long
2713 sys32_brk (unsigned int brk)
2714 {
2715         unsigned long ret, obrk;
2716         struct mm_struct *mm = current->mm;
2717
2718         obrk = mm->brk;
2719         ret = sys_brk(brk);
2720         if (ret < obrk)
2721                 clear_user((void *) ret, PAGE_ALIGN(ret) - ret);
2722         return ret;
2723 }
2724
2725 /*
2726  * Exactly like fs/open.c:sys_open(), except that it doesn't set the O_LARGEFILE flag.
2727  */
2728 asmlinkage long
2729 sys32_open (const char * filename, int flags, int mode)
2730 {
2731         char * tmp;
2732         int fd, error;
2733
2734         tmp = getname(filename);
2735         fd = PTR_ERR(tmp);
2736         if (!IS_ERR(tmp)) {
2737                 fd = get_unused_fd();
2738                 if (fd >= 0) {
2739                         struct file *f = filp_open(tmp, flags, mode);
2740                         error = PTR_ERR(f);
2741                         if (IS_ERR(f))
2742                                 goto out_error;
2743                         fd_install(fd, f);
2744                 }
2745 out:
2746                 putname(tmp);
2747         }
2748         return fd;
2749
2750 out_error:
2751         put_unused_fd(fd);
2752         fd = error;
2753         goto out;
2754 }
2755
2756 /* Structure for ia32 emulation on ia64 */
2757 struct epoll_event32
2758 {
2759         u32 events;
2760         u32 data[2];
2761 }; 
2762
2763 asmlinkage long
2764 sys32_epoll_ctl(int epfd, int op, int fd, struct epoll_event32 *event)
2765 {
2766         mm_segment_t old_fs = get_fs();
2767         struct epoll_event event64;
2768         int error = -EFAULT;
2769         u32 data_halfword;
2770
2771         if ((error = verify_area(VERIFY_READ, event,
2772                                  sizeof(struct epoll_event32))))
2773                 return error;
2774
2775         __get_user(event64.events, &event->events);
2776         __get_user(data_halfword, &event->data[0]);
2777         event64.data = data_halfword;
2778         __get_user(data_halfword, &event->data[1]);
2779         event64.data |= (u64)data_halfword << 32;
2780
2781         set_fs(KERNEL_DS);
2782         error = sys_epoll_ctl(epfd, op, fd, &event64);
2783         set_fs(old_fs);
2784
2785         return error;
2786 }
2787
2788 asmlinkage long
2789 sys32_epoll_wait(int epfd, struct epoll_event32 *events, int maxevents,
2790                  int timeout)
2791 {
2792         struct epoll_event *events64 = NULL;
2793         mm_segment_t old_fs = get_fs();
2794         int error, numevents, size;
2795         int evt_idx;
2796         int do_free_pages = 0;
2797
2798         if (maxevents <= 0) {
2799                 return -EINVAL;
2800         }
2801
2802         /* Verify that the area passed by the user is writeable */
2803         if ((error = verify_area(VERIFY_WRITE, events,
2804                                  maxevents * sizeof(struct epoll_event32))))
2805                 return error;
2806
2807         /* 
2808          * Allocate space for the intermediate copy.  If the space needed 
2809          * is large enough to cause kmalloc to fail, then try again with
2810          * __get_free_pages.
2811          */
2812         size = maxevents * sizeof(struct epoll_event);
2813         events64 = kmalloc(size, GFP_KERNEL);
2814         if (events64 == NULL) {
2815                 events64 = (struct epoll_event *)
2816                                 __get_free_pages(GFP_KERNEL, get_order(size));
2817                 if (events64 == NULL) 
2818                         return -ENOMEM;
2819                 do_free_pages = 1;
2820         }
2821
2822         /* Do the system call */
2823         set_fs(KERNEL_DS); /* copy_to/from_user should work on kernel mem*/
2824         numevents = sys_epoll_wait(epfd, events64, maxevents, timeout);
2825         set_fs(old_fs);
2826
2827         /* Don't modify userspace memory if we're returning an error */
2828         if (numevents > 0) {
2829                 /* Translate the 64-bit structures back into the 32-bit
2830                    structures */
2831                 for (evt_idx = 0; evt_idx < numevents; evt_idx++) {
2832                         __put_user(events64[evt_idx].events,
2833                                    &events[evt_idx].events);
2834                         __put_user((u32)events64[evt_idx].data,
2835                                    &events[evt_idx].data[0]);
2836                         __put_user((u32)(events64[evt_idx].data >> 32),
2837                                    &events[evt_idx].data[1]);
2838                 }
2839         }
2840
2841         if (do_free_pages)
2842                 free_pages((unsigned long) events64, get_order(size));
2843         else
2844                 kfree(events64);
2845         return numevents;
2846 }
2847
2848 /*
2849  * Get a yet unused TLS descriptor index.
2850  */
2851 static int
2852 get_free_idx (void)
2853 {
2854         struct thread_struct *t = &current->thread;
2855         int idx;
2856
2857         for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++)
2858                 if (desc_empty(t->tls_array + idx))
2859                         return idx + GDT_ENTRY_TLS_MIN;
2860         return -ESRCH;
2861 }
2862
2863 /*
2864  * Set a given TLS descriptor:
2865  */
2866 asmlinkage int
2867 sys32_set_thread_area (struct ia32_user_desc *u_info)
2868 {
2869         struct thread_struct *t = &current->thread;
2870         struct ia32_user_desc info;
2871         struct desc_struct *desc;
2872         int cpu, idx;
2873
2874         if (copy_from_user(&info, u_info, sizeof(info)))
2875                 return -EFAULT;
2876         idx = info.entry_number;
2877
2878         /*
2879          * index -1 means the kernel should try to find and allocate an empty descriptor:
2880          */
2881         if (idx == -1) {
2882                 idx = get_free_idx();
2883                 if (idx < 0)
2884                         return idx;
2885                 if (put_user(idx, &u_info->entry_number))
2886                         return -EFAULT;
2887         }
2888
2889         if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
2890                 return -EINVAL;
2891
2892         desc = t->tls_array + idx - GDT_ENTRY_TLS_MIN;
2893
2894         cpu = smp_processor_id();
2895
2896         if (LDT_empty(&info)) {
2897                 desc->a = 0;
2898                 desc->b = 0;
2899         } else {
2900                 desc->a = LDT_entry_a(&info);
2901                 desc->b = LDT_entry_b(&info);
2902         }
2903         load_TLS(t, cpu);
2904         return 0;
2905 }
2906
2907 /*
2908  * Get the current Thread-Local Storage area:
2909  */
2910
2911 #define GET_BASE(desc) (                        \
2912         (((desc)->a >> 16) & 0x0000ffff) |      \
2913         (((desc)->b << 16) & 0x00ff0000) |      \
2914         ( (desc)->b        & 0xff000000)   )
2915
2916 #define GET_LIMIT(desc) (                       \
2917         ((desc)->a & 0x0ffff) |                 \
2918          ((desc)->b & 0xf0000) )
2919
2920 #define GET_32BIT(desc)         (((desc)->b >> 23) & 1)
2921 #define GET_CONTENTS(desc)      (((desc)->b >> 10) & 3)
2922 #define GET_WRITABLE(desc)      (((desc)->b >>  9) & 1)
2923 #define GET_LIMIT_PAGES(desc)   (((desc)->b >> 23) & 1)
2924 #define GET_PRESENT(desc)       (((desc)->b >> 15) & 1)
2925 #define GET_USEABLE(desc)       (((desc)->b >> 20) & 1)
2926
2927 asmlinkage int
2928 sys32_get_thread_area (struct ia32_user_desc *u_info)
2929 {
2930         struct ia32_user_desc info;
2931         struct desc_struct *desc;
2932         int idx;
2933
2934         if (get_user(idx, &u_info->entry_number))
2935                 return -EFAULT;
2936         if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
2937                 return -EINVAL;
2938
2939         desc = current->thread.tls_array + idx - GDT_ENTRY_TLS_MIN;
2940
2941         info.entry_number = idx;
2942         info.base_addr = GET_BASE(desc);
2943         info.limit = GET_LIMIT(desc);
2944         info.seg_32bit = GET_32BIT(desc);
2945         info.contents = GET_CONTENTS(desc);
2946         info.read_exec_only = !GET_WRITABLE(desc);
2947         info.limit_in_pages = GET_LIMIT_PAGES(desc);
2948         info.seg_not_present = !GET_PRESENT(desc);
2949         info.useable = GET_USEABLE(desc);
2950
2951         if (copy_to_user(u_info, &info, sizeof(info)))
2952                 return -EFAULT;
2953         return 0;
2954 }
2955
2956 extern asmlinkage long
2957 sys_timer_create(clockid_t which_clock, struct sigevent *timer_event_spec,
2958                  timer_t * created_timer_id);
2959
2960 asmlinkage long
2961 sys32_timer_create(u32 clock, struct sigevent32 *se32, timer_t *timer_id)
2962 {
2963         struct sigevent se;
2964         mm_segment_t oldfs;
2965         timer_t t;
2966         long err;
2967
2968         if (se32 == NULL)
2969                 return sys_timer_create(clock, NULL, timer_id);
2970
2971         memset(&se, 0, sizeof(struct sigevent));
2972         if (get_user(se.sigev_value.sival_int,  &se32->sigev_value.sival_int) ||
2973             __get_user(se.sigev_signo, &se32->sigev_signo) ||
2974             __get_user(se.sigev_notify, &se32->sigev_notify) ||
2975             __copy_from_user(&se._sigev_un._pad, &se32->_sigev_un._pad,
2976             sizeof(se._sigev_un._pad)))
2977                 return -EFAULT;
2978
2979         if (!access_ok(VERIFY_WRITE,timer_id,sizeof(timer_t)))
2980                 return -EFAULT;
2981
2982         oldfs = get_fs();
2983         set_fs(KERNEL_DS);
2984         err = sys_timer_create(clock, &se, &t);
2985         set_fs(oldfs);
2986
2987         if (!err)
2988                 err = __put_user (t, timer_id);
2989
2990         return err;
2991 }
2992
2993 extern long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice);
2994
2995 long sys32_fadvise64_64(int fd, __u32 offset_low, __u32 offset_high, 
2996                         __u32 len_low, __u32 len_high, int advice)
2997
2998         return sys_fadvise64_64(fd,
2999                                (((u64)offset_high)<<32) | offset_low,
3000                                (((u64)len_high)<<32) | len_low,
3001                                advice); 
3002
3003
3004 #ifdef  NOTYET  /* UNTESTED FOR IA64 FROM HERE DOWN */
3005
3006 struct ncp_mount_data32 {
3007         int version;
3008         unsigned int ncp_fd;
3009         compat_uid_t mounted_uid;
3010         int wdog_pid;
3011         unsigned char mounted_vol[NCP_VOLNAME_LEN + 1];
3012         unsigned int time_out;
3013         unsigned int retry_count;
3014         unsigned int flags;
3015         compat_uid_t uid;
3016         compat_gid_t gid;
3017         compat_mode_t file_mode;
3018         compat_mode_t dir_mode;
3019 };
3020
3021 static void *
3022 do_ncp_super_data_conv(void *raw_data)
3023 {
3024         struct ncp_mount_data *n = (struct ncp_mount_data *)raw_data;
3025         struct ncp_mount_data32 *n32 = (struct ncp_mount_data32 *)raw_data;
3026
3027         n->dir_mode = n32->dir_mode;
3028         n->file_mode = n32->file_mode;
3029         n->gid = n32->gid;
3030         n->uid = n32->uid;
3031         memmove (n->mounted_vol, n32->mounted_vol,
3032                  (sizeof (n32->mounted_vol) + 3 * sizeof (unsigned int)));
3033         n->wdog_pid = n32->wdog_pid;
3034         n->mounted_uid = n32->mounted_uid;
3035         return raw_data;
3036 }
3037
3038 struct smb_mount_data32 {
3039         int version;
3040         compat_uid_t mounted_uid;
3041         compat_uid_t uid;
3042         compat_gid_t gid;
3043         compat_mode_t file_mode;
3044         compat_mode_t dir_mode;
3045 };
3046
3047 static void *
3048 do_smb_super_data_conv(void *raw_data)
3049 {
3050         struct smb_mount_data *s = (struct smb_mount_data *)raw_data;
3051         struct smb_mount_data32 *s32 = (struct smb_mount_data32 *)raw_data;
3052
3053         if (s32->version != SMB_MOUNT_OLDVERSION)
3054                 goto out;
3055         s->version = s32->version;
3056         s->mounted_uid = s32->mounted_uid;
3057         s->uid = s32->uid;
3058         s->gid = s32->gid;
3059         s->file_mode = s32->file_mode;
3060         s->dir_mode = s32->dir_mode;
3061 out:
3062         return raw_data;
3063 }
3064
3065 static int
3066 copy_mount_stuff_to_kernel(const void *user, unsigned long *kernel)
3067 {
3068         int i;
3069         unsigned long page;
3070         struct vm_area_struct *vma;
3071
3072         *kernel = 0;
3073         if(!user)
3074                 return 0;
3075         vma = find_vma(current->mm, (unsigned long)user);
3076         if(!vma || (unsigned long)user < vma->vm_start)
3077                 return -EFAULT;
3078         if(!(vma->vm_flags & VM_READ))
3079                 return -EFAULT;
3080         i = vma->vm_end - (unsigned long) user;
3081         if(PAGE_SIZE <= (unsigned long) i)
3082                 i = PAGE_SIZE - 1;
3083         if(!(page = __get_free_page(GFP_KERNEL)))
3084                 return -ENOMEM;
3085         if(copy_from_user((void *) page, user, i)) {
3086                 free_page(page);
3087                 return -EFAULT;
3088         }
3089         *kernel = page;
3090         return 0;
3091 }
3092
3093 extern asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type,
3094                                 unsigned long new_flags, void *data);
3095
3096 #define SMBFS_NAME      "smbfs"
3097 #define NCPFS_NAME      "ncpfs"
3098
3099 asmlinkage long
3100 sys32_mount(char *dev_name, char *dir_name, char *type,
3101             unsigned long new_flags, u32 data)
3102 {
3103         unsigned long type_page;
3104         int err, is_smb, is_ncp;
3105
3106         if(!capable(CAP_SYS_ADMIN))
3107                 return -EPERM;
3108         is_smb = is_ncp = 0;
3109         err = copy_mount_stuff_to_kernel((const void *)type, &type_page);
3110         if(err)
3111                 return err;
3112         if(type_page) {
3113                 is_smb = !strcmp((char *)type_page, SMBFS_NAME);
3114                 is_ncp = !strcmp((char *)type_page, NCPFS_NAME);
3115         }
3116         if(!is_smb && !is_ncp) {
3117                 if(type_page)
3118                         free_page(type_page);
3119                 return sys_mount(dev_name, dir_name, type, new_flags,
3120                                  (void *)AA(data));
3121         } else {
3122                 unsigned long dev_page, dir_page, data_page;
3123
3124                 err = copy_mount_stuff_to_kernel((const void *)dev_name,
3125                                                  &dev_page);
3126                 if(err)
3127                         goto out;
3128                 err = copy_mount_stuff_to_kernel((const void *)dir_name,
3129                                                  &dir_page);
3130                 if(err)
3131                         goto dev_out;
3132                 err = copy_mount_stuff_to_kernel((const void *)AA(data),
3133                                                  &data_page);
3134                 if(err)
3135                         goto dir_out;
3136                 if(is_ncp)
3137                         do_ncp_super_data_conv((void *)data_page);
3138                 else if(is_smb)
3139                         do_smb_super_data_conv((void *)data_page);
3140                 else
3141                         panic("The problem is here...");
3142                 err = do_mount((char *)dev_page, (char *)dir_page,
3143                                 (char *)type_page, new_flags,
3144                                 (void *)data_page);
3145                 if(data_page)
3146                         free_page(data_page);
3147         dir_out:
3148                 if(dir_page)
3149                         free_page(dir_page);
3150         dev_out:
3151                 if(dev_page)
3152                         free_page(dev_page);
3153         out:
3154                 if(type_page)
3155                         free_page(type_page);
3156                 return err;
3157         }
3158 }
3159
3160 extern asmlinkage long sys_setreuid(uid_t ruid, uid_t euid);
3161
3162 asmlinkage long sys32_setreuid(compat_uid_t ruid, compat_uid_t euid)
3163 {
3164         uid_t sruid, seuid;
3165
3166         sruid = (ruid == (compat_uid_t)-1) ? ((uid_t)-1) : ((uid_t)ruid);
3167         seuid = (euid == (compat_uid_t)-1) ? ((uid_t)-1) : ((uid_t)euid);
3168         return sys_setreuid(sruid, seuid);
3169 }
3170
3171 extern asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid);
3172
3173 asmlinkage long
3174 sys32_setresuid(compat_uid_t ruid, compat_uid_t euid,
3175                 compat_uid_t suid)
3176 {
3177         uid_t sruid, seuid, ssuid;
3178
3179         sruid = (ruid == (compat_uid_t)-1) ? ((uid_t)-1) : ((uid_t)ruid);
3180         seuid = (euid == (compat_uid_t)-1) ? ((uid_t)-1) : ((uid_t)euid);
3181         ssuid = (suid == (compat_uid_t)-1) ? ((uid_t)-1) : ((uid_t)suid);
3182         return sys_setresuid(sruid, seuid, ssuid);
3183 }
3184
3185 extern asmlinkage long sys_setregid(gid_t rgid, gid_t egid);
3186
3187 asmlinkage long
3188 sys32_setregid(compat_gid_t rgid, compat_gid_t egid)
3189 {
3190         gid_t srgid, segid;
3191
3192         srgid = (rgid == (compat_gid_t)-1) ? ((gid_t)-1) : ((gid_t)rgid);
3193         segid = (egid == (compat_gid_t)-1) ? ((gid_t)-1) : ((gid_t)egid);
3194         return sys_setregid(srgid, segid);
3195 }
3196
3197 extern asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid);
3198
3199 asmlinkage long
3200 sys32_setresgid(compat_gid_t rgid, compat_gid_t egid,
3201                 compat_gid_t sgid)
3202 {
3203         gid_t srgid, segid, ssgid;
3204
3205         srgid = (rgid == (compat_gid_t)-1) ? ((gid_t)-1) : ((gid_t)rgid);
3206         segid = (egid == (compat_gid_t)-1) ? ((gid_t)-1) : ((gid_t)egid);
3207         ssgid = (sgid == (compat_gid_t)-1) ? ((gid_t)-1) : ((gid_t)sgid);
3208         return sys_setresgid(srgid, segid, ssgid);
3209 }
3210
3211 /* Stuff for NFS server syscalls... */
3212 struct nfsctl_svc32 {
3213         u16                     svc32_port;
3214         s32                     svc32_nthreads;
3215 };
3216
3217 struct nfsctl_client32 {
3218         s8                      cl32_ident[NFSCLNT_IDMAX+1];
3219         s32                     cl32_naddr;
3220         struct in_addr          cl32_addrlist[NFSCLNT_ADDRMAX];
3221         s32                     cl32_fhkeytype;
3222         s32                     cl32_fhkeylen;
3223         u8                      cl32_fhkey[NFSCLNT_KEYMAX];
3224 };
3225
3226 struct nfsctl_export32 {
3227         s8                      ex32_client[NFSCLNT_IDMAX+1];
3228         s8                      ex32_path[NFS_MAXPATHLEN+1];
3229         compat_dev_t    ex32_dev;
3230         compat_ino_t    ex32_ino;
3231         s32                     ex32_flags;
3232         compat_uid_t    ex32_anon_uid;
3233         compat_gid_t    ex32_anon_gid;
3234 };
3235
3236 struct nfsctl_arg32 {
3237         s32                     ca32_version;   /* safeguard */
3238         union {
3239                 struct nfsctl_svc32     u32_svc;
3240                 struct nfsctl_client32  u32_client;
3241                 struct nfsctl_export32  u32_export;
3242                 u32                     u32_debug;
3243         } u;
3244 #define ca32_svc        u.u32_svc
3245 #define ca32_client     u.u32_client
3246 #define ca32_export     u.u32_export
3247 #define ca32_debug      u.u32_debug
3248 };
3249
3250 union nfsctl_res32 {
3251         struct knfs_fh          cr32_getfh;
3252         u32                     cr32_debug;
3253 };
3254
3255 static int
3256 nfs_svc32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3257 {
3258         int err;
3259
3260         err = __get_user(karg->ca_version, &arg32->ca32_version);
3261         err |= __get_user(karg->ca_svc.svc_port, &arg32->ca32_svc.svc32_port);
3262         err |= __get_user(karg->ca_svc.svc_nthreads,
3263                           &arg32->ca32_svc.svc32_nthreads);
3264         return err;
3265 }
3266
3267 static int
3268 nfs_clnt32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3269 {
3270         int err;
3271
3272         err = __get_user(karg->ca_version, &arg32->ca32_version);
3273         err |= copy_from_user(&karg->ca_client.cl_ident[0],
3274                           &arg32->ca32_client.cl32_ident[0],
3275                           NFSCLNT_IDMAX);
3276         err |= __get_user(karg->ca_client.cl_naddr,
3277                           &arg32->ca32_client.cl32_naddr);
3278         err |= copy_from_user(&karg->ca_client.cl_addrlist[0],
3279                           &arg32->ca32_client.cl32_addrlist[0],
3280                           (sizeof(struct in_addr) * NFSCLNT_ADDRMAX));
3281         err |= __get_user(karg->ca_client.cl_fhkeytype,
3282                       &arg32->ca32_client.cl32_fhkeytype);
3283         err |= __get_user(karg->ca_client.cl_fhkeylen,
3284                       &arg32->ca32_client.cl32_fhkeylen);
3285         err |= copy_from_user(&karg->ca_client.cl_fhkey[0],
3286                           &arg32->ca32_client.cl32_fhkey[0],
3287                           NFSCLNT_KEYMAX);
3288         return err;
3289 }
3290
3291 static int
3292 nfs_exp32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3293 {
3294         int err;
3295
3296         err = __get_user(karg->ca_version, &arg32->ca32_version);
3297         err |= copy_from_user(&karg->ca_export.ex_client[0],
3298                           &arg32->ca32_export.ex32_client[0],
3299                           NFSCLNT_IDMAX);
3300         err |= copy_from_user(&karg->ca_export.ex_path[0],
3301                           &arg32->ca32_export.ex32_path[0],
3302                           NFS_MAXPATHLEN);
3303         err |= __get_user(karg->ca_export.ex_dev,
3304                       &arg32->ca32_export.ex32_dev);
3305         err |= __get_user(karg->ca_export.ex_ino,
3306                       &arg32->ca32_export.ex32_ino);
3307         err |= __get_user(karg->ca_export.ex_flags,
3308                       &arg32->ca32_export.ex32_flags);
3309         err |= __get_user(karg->ca_export.ex_anon_uid,
3310                       &arg32->ca32_export.ex32_anon_uid);
3311         err |= __get_user(karg->ca_export.ex_anon_gid,
3312                       &arg32->ca32_export.ex32_anon_gid);
3313         return err;
3314 }
3315
3316 static int
3317 nfs_getfh32_res_trans(union nfsctl_res *kres, union nfsctl_res32 *res32)
3318 {
3319         int err;
3320
3321         err = copy_to_user(&res32->cr32_getfh,
3322                         &kres->cr_getfh,
3323                         sizeof(res32->cr32_getfh));
3324         err |= __put_user(kres->cr_debug, &res32->cr32_debug);
3325         return err;
3326 }
3327
3328 extern asmlinkage long sys_nfsservctl(int cmd, void *arg, void *resp);
3329
3330 int asmlinkage
3331 sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsctl_res32 *res32)
3332 {
3333         struct nfsctl_arg *karg = NULL;
3334         union nfsctl_res *kres = NULL;
3335         mm_segment_t oldfs;
3336         int err;
3337
3338         karg = kmalloc(sizeof(*karg), GFP_USER);
3339         if(!karg)
3340                 return -ENOMEM;
3341         if(res32) {
3342                 kres = kmalloc(sizeof(*kres), GFP_USER);
3343                 if(!kres) {
3344                         kfree(karg);
3345                         return -ENOMEM;
3346                 }
3347         }
3348         switch(cmd) {
3349         case NFSCTL_SVC:
3350                 err = nfs_svc32_trans(karg, arg32);
3351                 break;
3352         case NFSCTL_ADDCLIENT:
3353                 err = nfs_clnt32_trans(karg, arg32);
3354                 break;
3355         case NFSCTL_DELCLIENT:
3356                 err = nfs_clnt32_trans(karg, arg32);
3357                 break;
3358         case NFSCTL_EXPORT:
3359                 err = nfs_exp32_trans(karg, arg32);
3360                 break;
3361         default:
3362                 err = -EINVAL;
3363                 break;
3364         }
3365         if(err)
3366                 goto done;
3367         oldfs = get_fs();
3368         set_fs(KERNEL_DS);
3369         err = sys_nfsservctl(cmd, karg, kres);
3370         set_fs(oldfs);
3371
3372         if(!err && cmd == NFSCTL_GETFS)
3373                 err = nfs_getfh32_res_trans(kres, res32);
3374
3375 done:
3376         if(karg)
3377                 kfree(karg);
3378         if(kres)
3379                 kfree(kres);
3380         return err;
3381 }
3382
3383 /* Handle adjtimex compatibility. */
3384
3385 struct timex32 {
3386         u32 modes;
3387         s32 offset, freq, maxerror, esterror;
3388         s32 status, constant, precision, tolerance;
3389         struct compat_timeval time;
3390         s32 tick;
3391         s32 ppsfreq, jitter, shift, stabil;
3392         s32 jitcnt, calcnt, errcnt, stbcnt;
3393         s32  :32; s32  :32; s32  :32; s32  :32;
3394         s32  :32; s32  :32; s32  :32; s32  :32;
3395         s32  :32; s32  :32; s32  :32; s32  :32;
3396 };
3397
3398 extern int do_adjtimex(struct timex *);
3399
3400 asmlinkage long
3401 sys32_adjtimex(struct timex32 *utp)
3402 {
3403         struct timex txc;
3404         int ret;
3405
3406         memset(&txc, 0, sizeof(struct timex));
3407
3408         if(get_user(txc.modes, &utp->modes) ||
3409            __get_user(txc.offset, &utp->offset) ||
3410            __get_user(txc.freq, &utp->freq) ||
3411            __get_user(txc.maxerror, &utp->maxerror) ||
3412            __get_user(txc.esterror, &utp->esterror) ||
3413            __get_user(txc.status, &utp->status) ||
3414            __get_user(txc.constant, &utp->constant) ||
3415            __get_user(txc.precision, &utp->precision) ||
3416            __get_user(txc.tolerance, &utp->tolerance) ||
3417            __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
3418            __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
3419            __get_user(txc.tick, &utp->tick) ||
3420            __get_user(txc.ppsfreq, &utp->ppsfreq) ||
3421            __get_user(txc.jitter, &utp->jitter) ||
3422            __get_user(txc.shift, &utp->shift) ||
3423            __get_user(txc.stabil, &utp->stabil) ||
3424            __get_user(txc.jitcnt, &utp->jitcnt) ||
3425            __get_user(txc.calcnt, &utp->calcnt) ||
3426            __get_user(txc.errcnt, &utp->errcnt) ||
3427            __get_user(txc.stbcnt, &utp->stbcnt))
3428                 return -EFAULT;
3429
3430         ret = do_adjtimex(&txc);
3431
3432         if(put_user(txc.modes, &utp->modes) ||
3433            __put_user(txc.offset, &utp->offset) ||
3434            __put_user(txc.freq, &utp->freq) ||
3435            __put_user(txc.maxerror, &utp->maxerror) ||
3436            __put_user(txc.esterror, &utp->esterror) ||
3437            __put_user(txc.status, &utp->status) ||
3438            __put_user(txc.constant, &utp->constant) ||
3439            __put_user(txc.precision, &utp->precision) ||
3440            __put_user(txc.tolerance, &utp->tolerance) ||
3441            __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
3442            __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
3443            __put_user(txc.tick, &utp->tick) ||
3444            __put_user(txc.ppsfreq, &utp->ppsfreq) ||
3445            __put_user(txc.jitter, &utp->jitter) ||
3446            __put_user(txc.shift, &utp->shift) ||
3447            __put_user(txc.stabil, &utp->stabil) ||
3448            __put_user(txc.jitcnt, &utp->jitcnt) ||
3449            __put_user(txc.calcnt, &utp->calcnt) ||
3450            __put_user(txc.errcnt, &utp->errcnt) ||
3451            __put_user(txc.stbcnt, &utp->stbcnt))
3452                 ret = -EFAULT;
3453
3454         return ret;
3455 }
3456 #endif /* NOTYET */