xref: /linux/arch/parisc/kernel/sys_parisc32.c (revision 1da177e4)
1*1da177e4SLinus Torvalds /*
2*1da177e4SLinus Torvalds  * sys_parisc32.c: Conversion between 32bit and 64bit native syscalls.
3*1da177e4SLinus Torvalds  *
4*1da177e4SLinus Torvalds  * Copyright (C) 2000-2001 Hewlett Packard Company
5*1da177e4SLinus Torvalds  * Copyright (C) 2000 John Marvin
6*1da177e4SLinus Torvalds  * Copyright (C) 2001 Matthew Wilcox
7*1da177e4SLinus Torvalds  *
8*1da177e4SLinus Torvalds  * These routines maintain argument size conversion between 32bit and 64bit
9*1da177e4SLinus Torvalds  * environment. Based heavily on sys_ia32.c and sys_sparc32.c.
10*1da177e4SLinus Torvalds  */
11*1da177e4SLinus Torvalds 
12*1da177e4SLinus Torvalds #include <linux/config.h>
13*1da177e4SLinus Torvalds #include <linux/compat.h>
14*1da177e4SLinus Torvalds #include <linux/kernel.h>
15*1da177e4SLinus Torvalds #include <linux/sched.h>
16*1da177e4SLinus Torvalds #include <linux/fs.h>
17*1da177e4SLinus Torvalds #include <linux/mm.h>
18*1da177e4SLinus Torvalds #include <linux/file.h>
19*1da177e4SLinus Torvalds #include <linux/signal.h>
20*1da177e4SLinus Torvalds #include <linux/resource.h>
21*1da177e4SLinus Torvalds #include <linux/times.h>
22*1da177e4SLinus Torvalds #include <linux/utsname.h>
23*1da177e4SLinus Torvalds #include <linux/time.h>
24*1da177e4SLinus Torvalds #include <linux/timex.h>
25*1da177e4SLinus Torvalds #include <linux/smp.h>
26*1da177e4SLinus Torvalds #include <linux/smp_lock.h>
27*1da177e4SLinus Torvalds #include <linux/sem.h>
28*1da177e4SLinus Torvalds #include <linux/msg.h>
29*1da177e4SLinus Torvalds #include <linux/shm.h>
30*1da177e4SLinus Torvalds #include <linux/slab.h>
31*1da177e4SLinus Torvalds #include <linux/uio.h>
32*1da177e4SLinus Torvalds #include <linux/nfs_fs.h>
33*1da177e4SLinus Torvalds #include <linux/ncp_fs.h>
34*1da177e4SLinus Torvalds #include <linux/sunrpc/svc.h>
35*1da177e4SLinus Torvalds #include <linux/nfsd/nfsd.h>
36*1da177e4SLinus Torvalds #include <linux/nfsd/cache.h>
37*1da177e4SLinus Torvalds #include <linux/nfsd/xdr.h>
38*1da177e4SLinus Torvalds #include <linux/nfsd/syscall.h>
39*1da177e4SLinus Torvalds #include <linux/poll.h>
40*1da177e4SLinus Torvalds #include <linux/personality.h>
41*1da177e4SLinus Torvalds #include <linux/stat.h>
42*1da177e4SLinus Torvalds #include <linux/highmem.h>
43*1da177e4SLinus Torvalds #include <linux/highuid.h>
44*1da177e4SLinus Torvalds #include <linux/mman.h>
45*1da177e4SLinus Torvalds #include <linux/binfmts.h>
46*1da177e4SLinus Torvalds #include <linux/namei.h>
47*1da177e4SLinus Torvalds #include <linux/vfs.h>
48*1da177e4SLinus Torvalds #include <linux/ptrace.h>
49*1da177e4SLinus Torvalds #include <linux/swap.h>
50*1da177e4SLinus Torvalds #include <linux/syscalls.h>
51*1da177e4SLinus Torvalds 
52*1da177e4SLinus Torvalds #include <asm/types.h>
53*1da177e4SLinus Torvalds #include <asm/uaccess.h>
54*1da177e4SLinus Torvalds #include <asm/semaphore.h>
55*1da177e4SLinus Torvalds #include <asm/mmu_context.h>
56*1da177e4SLinus Torvalds 
57*1da177e4SLinus Torvalds #include "sys32.h"
58*1da177e4SLinus Torvalds 
59*1da177e4SLinus Torvalds #undef DEBUG
60*1da177e4SLinus Torvalds 
61*1da177e4SLinus Torvalds #ifdef DEBUG
62*1da177e4SLinus Torvalds #define DBG(x)	printk x
63*1da177e4SLinus Torvalds #else
64*1da177e4SLinus Torvalds #define DBG(x)
65*1da177e4SLinus Torvalds #endif
66*1da177e4SLinus Torvalds 
67*1da177e4SLinus Torvalds /*
68*1da177e4SLinus Torvalds  * sys32_execve() executes a new program.
69*1da177e4SLinus Torvalds  */
70*1da177e4SLinus Torvalds 
71*1da177e4SLinus Torvalds asmlinkage int sys32_execve(struct pt_regs *regs)
72*1da177e4SLinus Torvalds {
73*1da177e4SLinus Torvalds 	int error;
74*1da177e4SLinus Torvalds 	char *filename;
75*1da177e4SLinus Torvalds 
76*1da177e4SLinus Torvalds 	DBG(("sys32_execve(%p) r26 = 0x%lx\n", regs, regs->gr[26]));
77*1da177e4SLinus Torvalds 	filename = getname((const char __user *) regs->gr[26]);
78*1da177e4SLinus Torvalds 	error = PTR_ERR(filename);
79*1da177e4SLinus Torvalds 	if (IS_ERR(filename))
80*1da177e4SLinus Torvalds 		goto out;
81*1da177e4SLinus Torvalds 	error = compat_do_execve(filename, compat_ptr(regs->gr[25]),
82*1da177e4SLinus Torvalds 				 compat_ptr(regs->gr[24]), regs);
83*1da177e4SLinus Torvalds 	if (error == 0) {
84*1da177e4SLinus Torvalds 		task_lock(current);
85*1da177e4SLinus Torvalds 		current->ptrace &= ~PT_DTRACE;
86*1da177e4SLinus Torvalds 		task_unlock(current);
87*1da177e4SLinus Torvalds 	}
88*1da177e4SLinus Torvalds 	putname(filename);
89*1da177e4SLinus Torvalds out:
90*1da177e4SLinus Torvalds 
91*1da177e4SLinus Torvalds 	return error;
92*1da177e4SLinus Torvalds }
93*1da177e4SLinus Torvalds 
94*1da177e4SLinus Torvalds asmlinkage long sys32_unimplemented(int r26, int r25, int r24, int r23,
95*1da177e4SLinus Torvalds 	int r22, int r21, int r20)
96*1da177e4SLinus Torvalds {
97*1da177e4SLinus Torvalds     printk(KERN_ERR "%s(%d): Unimplemented 32 on 64 syscall #%d!\n",
98*1da177e4SLinus Torvalds     	current->comm, current->pid, r20);
99*1da177e4SLinus Torvalds     return -ENOSYS;
100*1da177e4SLinus Torvalds }
101*1da177e4SLinus Torvalds 
102*1da177e4SLinus Torvalds #ifdef CONFIG_SYSCTL
103*1da177e4SLinus Torvalds 
104*1da177e4SLinus Torvalds struct __sysctl_args32 {
105*1da177e4SLinus Torvalds 	u32 name;
106*1da177e4SLinus Torvalds 	int nlen;
107*1da177e4SLinus Torvalds 	u32 oldval;
108*1da177e4SLinus Torvalds 	u32 oldlenp;
109*1da177e4SLinus Torvalds 	u32 newval;
110*1da177e4SLinus Torvalds 	u32 newlen;
111*1da177e4SLinus Torvalds 	u32 __unused[4];
112*1da177e4SLinus Torvalds };
113*1da177e4SLinus Torvalds 
114*1da177e4SLinus Torvalds asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
115*1da177e4SLinus Torvalds {
116*1da177e4SLinus Torvalds 	struct __sysctl_args32 tmp;
117*1da177e4SLinus Torvalds 	int error;
118*1da177e4SLinus Torvalds 	unsigned int oldlen32;
119*1da177e4SLinus Torvalds 	size_t oldlen, *oldlenp = NULL;
120*1da177e4SLinus Torvalds 	unsigned long addr = (((long __force)&args->__unused[0]) + 7) & ~7;
121*1da177e4SLinus Torvalds 	extern int do_sysctl(int *name, int nlen, void *oldval, size_t *oldlenp,
122*1da177e4SLinus Torvalds 	       void *newval, size_t newlen);
123*1da177e4SLinus Torvalds 
124*1da177e4SLinus Torvalds 	DBG(("sysctl32(%p)\n", args));
125*1da177e4SLinus Torvalds 
126*1da177e4SLinus Torvalds 	if (copy_from_user(&tmp, args, sizeof(tmp)))
127*1da177e4SLinus Torvalds 		return -EFAULT;
128*1da177e4SLinus Torvalds 
129*1da177e4SLinus Torvalds 	if (tmp.oldval && tmp.oldlenp) {
130*1da177e4SLinus Torvalds 		/* Duh, this is ugly and might not work if sysctl_args
131*1da177e4SLinus Torvalds 		   is in read-only memory, but do_sysctl does indirectly
132*1da177e4SLinus Torvalds 		   a lot of uaccess in both directions and we'd have to
133*1da177e4SLinus Torvalds 		   basically copy the whole sysctl.c here, and
134*1da177e4SLinus Torvalds 		   glibc's __sysctl uses rw memory for the structure
135*1da177e4SLinus Torvalds 		   anyway.  */
136*1da177e4SLinus Torvalds 		/* a possibly better hack than this, which will avoid the
137*1da177e4SLinus Torvalds 		 * problem if the struct is read only, is to push the
138*1da177e4SLinus Torvalds 		 * 'oldlen' value out to the user's stack instead. -PB
139*1da177e4SLinus Torvalds 		 */
140*1da177e4SLinus Torvalds 		if (get_user(oldlen32, (u32 *)(u64)tmp.oldlenp))
141*1da177e4SLinus Torvalds 			return -EFAULT;
142*1da177e4SLinus Torvalds 		oldlen = oldlen32;
143*1da177e4SLinus Torvalds 		if (put_user(oldlen, (size_t *)addr))
144*1da177e4SLinus Torvalds 			return -EFAULT;
145*1da177e4SLinus Torvalds 		oldlenp = (size_t *)addr;
146*1da177e4SLinus Torvalds 	}
147*1da177e4SLinus Torvalds 
148*1da177e4SLinus Torvalds 	lock_kernel();
149*1da177e4SLinus Torvalds 	error = do_sysctl((int *)(u64)tmp.name, tmp.nlen, (void *)(u64)tmp.oldval,
150*1da177e4SLinus Torvalds 			  oldlenp, (void *)(u64)tmp.newval, tmp.newlen);
151*1da177e4SLinus Torvalds 	unlock_kernel();
152*1da177e4SLinus Torvalds 	if (oldlenp) {
153*1da177e4SLinus Torvalds 		if (!error) {
154*1da177e4SLinus Torvalds 			if (get_user(oldlen, (size_t *)addr)) {
155*1da177e4SLinus Torvalds 				error = -EFAULT;
156*1da177e4SLinus Torvalds 			} else {
157*1da177e4SLinus Torvalds 				oldlen32 = oldlen;
158*1da177e4SLinus Torvalds 				if (put_user(oldlen32, (u32 *)(u64)tmp.oldlenp))
159*1da177e4SLinus Torvalds 					error = -EFAULT;
160*1da177e4SLinus Torvalds 			}
161*1da177e4SLinus Torvalds 		}
162*1da177e4SLinus Torvalds 		if (copy_to_user(&args->__unused[0], tmp.__unused, sizeof(tmp.__unused)))
163*1da177e4SLinus Torvalds 			error = -EFAULT;
164*1da177e4SLinus Torvalds 	}
165*1da177e4SLinus Torvalds 	return error;
166*1da177e4SLinus Torvalds }
167*1da177e4SLinus Torvalds 
168*1da177e4SLinus Torvalds #endif /* CONFIG_SYSCTL */
169*1da177e4SLinus Torvalds 
170*1da177e4SLinus Torvalds asmlinkage long sys32_sched_rr_get_interval(pid_t pid,
171*1da177e4SLinus Torvalds 	struct compat_timespec __user *interval)
172*1da177e4SLinus Torvalds {
173*1da177e4SLinus Torvalds 	struct timespec t;
174*1da177e4SLinus Torvalds 	int ret;
175*1da177e4SLinus Torvalds 
176*1da177e4SLinus Torvalds 	KERNEL_SYSCALL(ret, sys_sched_rr_get_interval, pid, (struct timespec __user *)&t);
177*1da177e4SLinus Torvalds 	if (put_compat_timespec(&t, interval))
178*1da177e4SLinus Torvalds 		return -EFAULT;
179*1da177e4SLinus Torvalds 	return ret;
180*1da177e4SLinus Torvalds }
181*1da177e4SLinus Torvalds 
182*1da177e4SLinus Torvalds static int
183*1da177e4SLinus Torvalds put_compat_timeval(struct compat_timeval __user *u, struct timeval *t)
184*1da177e4SLinus Torvalds {
185*1da177e4SLinus Torvalds 	struct compat_timeval t32;
186*1da177e4SLinus Torvalds 	t32.tv_sec = t->tv_sec;
187*1da177e4SLinus Torvalds 	t32.tv_usec = t->tv_usec;
188*1da177e4SLinus Torvalds 	return copy_to_user(u, &t32, sizeof t32);
189*1da177e4SLinus Torvalds }
190*1da177e4SLinus Torvalds 
191*1da177e4SLinus Torvalds static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
192*1da177e4SLinus Torvalds {
193*1da177e4SLinus Torvalds 	long usec;
194*1da177e4SLinus Torvalds 
195*1da177e4SLinus Torvalds 	if (__get_user(o->tv_sec, &i->tv_sec))
196*1da177e4SLinus Torvalds 		return -EFAULT;
197*1da177e4SLinus Torvalds 	if (__get_user(usec, &i->tv_usec))
198*1da177e4SLinus Torvalds 		return -EFAULT;
199*1da177e4SLinus Torvalds 	o->tv_nsec = usec * 1000;
200*1da177e4SLinus Torvalds 	return 0;
201*1da177e4SLinus Torvalds }
202*1da177e4SLinus Torvalds 
203*1da177e4SLinus Torvalds asmlinkage int
204*1da177e4SLinus Torvalds sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
205*1da177e4SLinus Torvalds {
206*1da177e4SLinus Torvalds     extern void do_gettimeofday(struct timeval *tv);
207*1da177e4SLinus Torvalds 
208*1da177e4SLinus Torvalds     if (tv) {
209*1da177e4SLinus Torvalds 	    struct timeval ktv;
210*1da177e4SLinus Torvalds 	    do_gettimeofday(&ktv);
211*1da177e4SLinus Torvalds 	    if (put_compat_timeval(tv, &ktv))
212*1da177e4SLinus Torvalds 		    return -EFAULT;
213*1da177e4SLinus Torvalds     }
214*1da177e4SLinus Torvalds     if (tz) {
215*1da177e4SLinus Torvalds 	    extern struct timezone sys_tz;
216*1da177e4SLinus Torvalds 	    if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
217*1da177e4SLinus Torvalds 		    return -EFAULT;
218*1da177e4SLinus Torvalds     }
219*1da177e4SLinus Torvalds     return 0;
220*1da177e4SLinus Torvalds }
221*1da177e4SLinus Torvalds 
222*1da177e4SLinus Torvalds asmlinkage
223*1da177e4SLinus Torvalds int sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
224*1da177e4SLinus Torvalds {
225*1da177e4SLinus Torvalds 	struct timespec kts;
226*1da177e4SLinus Torvalds 	struct timezone ktz;
227*1da177e4SLinus Torvalds 
228*1da177e4SLinus Torvalds  	if (tv) {
229*1da177e4SLinus Torvalds 		if (get_ts32(&kts, tv))
230*1da177e4SLinus Torvalds 			return -EFAULT;
231*1da177e4SLinus Torvalds 	}
232*1da177e4SLinus Torvalds 	if (tz) {
233*1da177e4SLinus Torvalds 		if (copy_from_user(&ktz, tz, sizeof(ktz)))
234*1da177e4SLinus Torvalds 			return -EFAULT;
235*1da177e4SLinus Torvalds 	}
236*1da177e4SLinus Torvalds 
237*1da177e4SLinus Torvalds 	return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
238*1da177e4SLinus Torvalds }
239*1da177e4SLinus Torvalds 
240*1da177e4SLinus Torvalds int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
241*1da177e4SLinus Torvalds {
242*1da177e4SLinus Torvalds 	int err;
243*1da177e4SLinus Torvalds 
244*1da177e4SLinus Torvalds 	if (stat->size > MAX_NON_LFS || !new_valid_dev(stat->dev) ||
245*1da177e4SLinus Torvalds 	    !new_valid_dev(stat->rdev))
246*1da177e4SLinus Torvalds 		return -EOVERFLOW;
247*1da177e4SLinus Torvalds 
248*1da177e4SLinus Torvalds 	err  = put_user(new_encode_dev(stat->dev), &statbuf->st_dev);
249*1da177e4SLinus Torvalds 	err |= put_user(stat->ino, &statbuf->st_ino);
250*1da177e4SLinus Torvalds 	err |= put_user(stat->mode, &statbuf->st_mode);
251*1da177e4SLinus Torvalds 	err |= put_user(stat->nlink, &statbuf->st_nlink);
252*1da177e4SLinus Torvalds 	err |= put_user(0, &statbuf->st_reserved1);
253*1da177e4SLinus Torvalds 	err |= put_user(0, &statbuf->st_reserved2);
254*1da177e4SLinus Torvalds 	err |= put_user(new_encode_dev(stat->rdev), &statbuf->st_rdev);
255*1da177e4SLinus Torvalds 	err |= put_user(stat->size, &statbuf->st_size);
256*1da177e4SLinus Torvalds 	err |= put_user(stat->atime.tv_sec, &statbuf->st_atime);
257*1da177e4SLinus Torvalds 	err |= put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec);
258*1da177e4SLinus Torvalds 	err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime);
259*1da177e4SLinus Torvalds 	err |= put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec);
260*1da177e4SLinus Torvalds 	err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime);
261*1da177e4SLinus Torvalds 	err |= put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec);
262*1da177e4SLinus Torvalds 	err |= put_user(stat->blksize, &statbuf->st_blksize);
263*1da177e4SLinus Torvalds 	err |= put_user(stat->blocks, &statbuf->st_blocks);
264*1da177e4SLinus Torvalds 	err |= put_user(0, &statbuf->__unused1);
265*1da177e4SLinus Torvalds 	err |= put_user(0, &statbuf->__unused2);
266*1da177e4SLinus Torvalds 	err |= put_user(0, &statbuf->__unused3);
267*1da177e4SLinus Torvalds 	err |= put_user(0, &statbuf->__unused4);
268*1da177e4SLinus Torvalds 	err |= put_user(0, &statbuf->__unused5);
269*1da177e4SLinus Torvalds 	err |= put_user(0, &statbuf->st_fstype); /* not avail */
270*1da177e4SLinus Torvalds 	err |= put_user(0, &statbuf->st_realdev); /* not avail */
271*1da177e4SLinus Torvalds 	err |= put_user(0, &statbuf->st_basemode); /* not avail */
272*1da177e4SLinus Torvalds 	err |= put_user(0, &statbuf->st_spareshort);
273*1da177e4SLinus Torvalds 	err |= put_user(stat->uid, &statbuf->st_uid);
274*1da177e4SLinus Torvalds 	err |= put_user(stat->gid, &statbuf->st_gid);
275*1da177e4SLinus Torvalds 	err |= put_user(0, &statbuf->st_spare4[0]);
276*1da177e4SLinus Torvalds 	err |= put_user(0, &statbuf->st_spare4[1]);
277*1da177e4SLinus Torvalds 	err |= put_user(0, &statbuf->st_spare4[2]);
278*1da177e4SLinus Torvalds 
279*1da177e4SLinus Torvalds 	return err;
280*1da177e4SLinus Torvalds }
281*1da177e4SLinus Torvalds 
282*1da177e4SLinus Torvalds struct linux32_dirent {
283*1da177e4SLinus Torvalds 	u32		d_ino;
284*1da177e4SLinus Torvalds 	compat_off_t	d_off;
285*1da177e4SLinus Torvalds 	u16		d_reclen;
286*1da177e4SLinus Torvalds 	char		d_name[1];
287*1da177e4SLinus Torvalds };
288*1da177e4SLinus Torvalds 
289*1da177e4SLinus Torvalds struct old_linux32_dirent {
290*1da177e4SLinus Torvalds 	u32	d_ino;
291*1da177e4SLinus Torvalds 	u32	d_offset;
292*1da177e4SLinus Torvalds 	u16	d_namlen;
293*1da177e4SLinus Torvalds 	char	d_name[1];
294*1da177e4SLinus Torvalds };
295*1da177e4SLinus Torvalds 
296*1da177e4SLinus Torvalds struct getdents32_callback {
297*1da177e4SLinus Torvalds 	struct linux32_dirent __user * current_dir;
298*1da177e4SLinus Torvalds 	struct linux32_dirent __user * previous;
299*1da177e4SLinus Torvalds 	int count;
300*1da177e4SLinus Torvalds 	int error;
301*1da177e4SLinus Torvalds };
302*1da177e4SLinus Torvalds 
303*1da177e4SLinus Torvalds struct readdir32_callback {
304*1da177e4SLinus Torvalds 	struct old_linux32_dirent __user * dirent;
305*1da177e4SLinus Torvalds 	int count;
306*1da177e4SLinus Torvalds };
307*1da177e4SLinus Torvalds 
308*1da177e4SLinus Torvalds #define ROUND_UP(x,a)	((__typeof__(x))(((unsigned long)(x) + ((a) - 1)) & ~((a) - 1)))
309*1da177e4SLinus Torvalds #define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
310*1da177e4SLinus Torvalds static int
311*1da177e4SLinus Torvalds filldir32 (void *__buf, const char *name, int namlen, loff_t offset, ino_t ino,
312*1da177e4SLinus Torvalds 	   unsigned int d_type)
313*1da177e4SLinus Torvalds {
314*1da177e4SLinus Torvalds 	struct linux32_dirent __user * dirent;
315*1da177e4SLinus Torvalds 	struct getdents32_callback * buf = (struct getdents32_callback *) __buf;
316*1da177e4SLinus Torvalds 	int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1, 4);
317*1da177e4SLinus Torvalds 
318*1da177e4SLinus Torvalds 	buf->error = -EINVAL;	/* only used if we fail.. */
319*1da177e4SLinus Torvalds 	if (reclen > buf->count)
320*1da177e4SLinus Torvalds 		return -EINVAL;
321*1da177e4SLinus Torvalds 	dirent = buf->previous;
322*1da177e4SLinus Torvalds 	if (dirent)
323*1da177e4SLinus Torvalds 		put_user(offset, &dirent->d_off);
324*1da177e4SLinus Torvalds 	dirent = buf->current_dir;
325*1da177e4SLinus Torvalds 	buf->previous = dirent;
326*1da177e4SLinus Torvalds 	put_user(ino, &dirent->d_ino);
327*1da177e4SLinus Torvalds 	put_user(reclen, &dirent->d_reclen);
328*1da177e4SLinus Torvalds 	copy_to_user(dirent->d_name, name, namlen);
329*1da177e4SLinus Torvalds 	put_user(0, dirent->d_name + namlen);
330*1da177e4SLinus Torvalds 	dirent = ((void __user *)dirent) + reclen;
331*1da177e4SLinus Torvalds 	buf->current_dir = dirent;
332*1da177e4SLinus Torvalds 	buf->count -= reclen;
333*1da177e4SLinus Torvalds 	return 0;
334*1da177e4SLinus Torvalds }
335*1da177e4SLinus Torvalds 
336*1da177e4SLinus Torvalds asmlinkage long
337*1da177e4SLinus Torvalds sys32_getdents (unsigned int fd, void __user * dirent, unsigned int count)
338*1da177e4SLinus Torvalds {
339*1da177e4SLinus Torvalds 	struct file * file;
340*1da177e4SLinus Torvalds 	struct linux32_dirent __user * lastdirent;
341*1da177e4SLinus Torvalds 	struct getdents32_callback buf;
342*1da177e4SLinus Torvalds 	int error;
343*1da177e4SLinus Torvalds 
344*1da177e4SLinus Torvalds 	error = -EBADF;
345*1da177e4SLinus Torvalds 	file = fget(fd);
346*1da177e4SLinus Torvalds 	if (!file)
347*1da177e4SLinus Torvalds 		goto out;
348*1da177e4SLinus Torvalds 
349*1da177e4SLinus Torvalds 	buf.current_dir = (struct linux32_dirent __user *) dirent;
350*1da177e4SLinus Torvalds 	buf.previous = NULL;
351*1da177e4SLinus Torvalds 	buf.count = count;
352*1da177e4SLinus Torvalds 	buf.error = 0;
353*1da177e4SLinus Torvalds 
354*1da177e4SLinus Torvalds 	error = vfs_readdir(file, filldir32, &buf);
355*1da177e4SLinus Torvalds 	if (error < 0)
356*1da177e4SLinus Torvalds 		goto out_putf;
357*1da177e4SLinus Torvalds 	error = buf.error;
358*1da177e4SLinus Torvalds 	lastdirent = buf.previous;
359*1da177e4SLinus Torvalds 	if (lastdirent) {
360*1da177e4SLinus Torvalds 		put_user(file->f_pos, &lastdirent->d_off);
361*1da177e4SLinus Torvalds 		error = count - buf.count;
362*1da177e4SLinus Torvalds 	}
363*1da177e4SLinus Torvalds 
364*1da177e4SLinus Torvalds out_putf:
365*1da177e4SLinus Torvalds 	fput(file);
366*1da177e4SLinus Torvalds out:
367*1da177e4SLinus Torvalds 	return error;
368*1da177e4SLinus Torvalds }
369*1da177e4SLinus Torvalds 
370*1da177e4SLinus Torvalds static int
371*1da177e4SLinus Torvalds fillonedir32 (void * __buf, const char * name, int namlen, loff_t offset, ino_t ino,
372*1da177e4SLinus Torvalds 	      unsigned int d_type)
373*1da177e4SLinus Torvalds {
374*1da177e4SLinus Torvalds 	struct readdir32_callback * buf = (struct readdir32_callback *) __buf;
375*1da177e4SLinus Torvalds 	struct old_linux32_dirent __user * dirent;
376*1da177e4SLinus Torvalds 
377*1da177e4SLinus Torvalds 	if (buf->count)
378*1da177e4SLinus Torvalds 		return -EINVAL;
379*1da177e4SLinus Torvalds 	buf->count++;
380*1da177e4SLinus Torvalds 	dirent = buf->dirent;
381*1da177e4SLinus Torvalds 	put_user(ino, &dirent->d_ino);
382*1da177e4SLinus Torvalds 	put_user(offset, &dirent->d_offset);
383*1da177e4SLinus Torvalds 	put_user(namlen, &dirent->d_namlen);
384*1da177e4SLinus Torvalds 	copy_to_user(dirent->d_name, name, namlen);
385*1da177e4SLinus Torvalds 	put_user(0, dirent->d_name + namlen);
386*1da177e4SLinus Torvalds 	return 0;
387*1da177e4SLinus Torvalds }
388*1da177e4SLinus Torvalds 
389*1da177e4SLinus Torvalds asmlinkage long
390*1da177e4SLinus Torvalds sys32_readdir (unsigned int fd, void __user * dirent, unsigned int count)
391*1da177e4SLinus Torvalds {
392*1da177e4SLinus Torvalds 	int error;
393*1da177e4SLinus Torvalds 	struct file * file;
394*1da177e4SLinus Torvalds 	struct readdir32_callback buf;
395*1da177e4SLinus Torvalds 
396*1da177e4SLinus Torvalds 	error = -EBADF;
397*1da177e4SLinus Torvalds 	file = fget(fd);
398*1da177e4SLinus Torvalds 	if (!file)
399*1da177e4SLinus Torvalds 		goto out;
400*1da177e4SLinus Torvalds 
401*1da177e4SLinus Torvalds 	buf.count = 0;
402*1da177e4SLinus Torvalds 	buf.dirent = dirent;
403*1da177e4SLinus Torvalds 
404*1da177e4SLinus Torvalds 	error = vfs_readdir(file, fillonedir32, &buf);
405*1da177e4SLinus Torvalds 	if (error >= 0)
406*1da177e4SLinus Torvalds 		error = buf.count;
407*1da177e4SLinus Torvalds 	fput(file);
408*1da177e4SLinus Torvalds out:
409*1da177e4SLinus Torvalds 	return error;
410*1da177e4SLinus Torvalds }
411*1da177e4SLinus Torvalds 
412*1da177e4SLinus Torvalds /*** copied from mips64 ***/
413*1da177e4SLinus Torvalds /*
414*1da177e4SLinus Torvalds  * Ooo, nasty.  We need here to frob 32-bit unsigned longs to
415*1da177e4SLinus Torvalds  * 64-bit unsigned longs.
416*1da177e4SLinus Torvalds  */
417*1da177e4SLinus Torvalds 
418*1da177e4SLinus Torvalds static inline int
419*1da177e4SLinus Torvalds get_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset)
420*1da177e4SLinus Torvalds {
421*1da177e4SLinus Torvalds 	n = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32));
422*1da177e4SLinus Torvalds 	if (ufdset) {
423*1da177e4SLinus Torvalds 		unsigned long odd;
424*1da177e4SLinus Torvalds 
425*1da177e4SLinus Torvalds 		if (!access_ok(VERIFY_WRITE, ufdset, n*sizeof(u32)))
426*1da177e4SLinus Torvalds 			return -EFAULT;
427*1da177e4SLinus Torvalds 
428*1da177e4SLinus Torvalds 		odd = n & 1UL;
429*1da177e4SLinus Torvalds 		n &= ~1UL;
430*1da177e4SLinus Torvalds 		while (n) {
431*1da177e4SLinus Torvalds 			unsigned long h, l;
432*1da177e4SLinus Torvalds 			__get_user(l, ufdset);
433*1da177e4SLinus Torvalds 			__get_user(h, ufdset+1);
434*1da177e4SLinus Torvalds 			ufdset += 2;
435*1da177e4SLinus Torvalds 			*fdset++ = h << 32 | l;
436*1da177e4SLinus Torvalds 			n -= 2;
437*1da177e4SLinus Torvalds 		}
438*1da177e4SLinus Torvalds 		if (odd)
439*1da177e4SLinus Torvalds 			__get_user(*fdset, ufdset);
440*1da177e4SLinus Torvalds 	} else {
441*1da177e4SLinus Torvalds 		/* Tricky, must clear full unsigned long in the
442*1da177e4SLinus Torvalds 		 * kernel fdset at the end, this makes sure that
443*1da177e4SLinus Torvalds 		 * actually happens.
444*1da177e4SLinus Torvalds 		 */
445*1da177e4SLinus Torvalds 		memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32));
446*1da177e4SLinus Torvalds 	}
447*1da177e4SLinus Torvalds 	return 0;
448*1da177e4SLinus Torvalds }
449*1da177e4SLinus Torvalds 
450*1da177e4SLinus Torvalds static inline void
451*1da177e4SLinus Torvalds set_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset)
452*1da177e4SLinus Torvalds {
453*1da177e4SLinus Torvalds 	unsigned long odd;
454*1da177e4SLinus Torvalds 	n = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32));
455*1da177e4SLinus Torvalds 
456*1da177e4SLinus Torvalds 	if (!ufdset)
457*1da177e4SLinus Torvalds 		return;
458*1da177e4SLinus Torvalds 
459*1da177e4SLinus Torvalds 	odd = n & 1UL;
460*1da177e4SLinus Torvalds 	n &= ~1UL;
461*1da177e4SLinus Torvalds 	while (n) {
462*1da177e4SLinus Torvalds 		unsigned long h, l;
463*1da177e4SLinus Torvalds 		l = *fdset++;
464*1da177e4SLinus Torvalds 		h = l >> 32;
465*1da177e4SLinus Torvalds 		__put_user(l, ufdset);
466*1da177e4SLinus Torvalds 		__put_user(h, ufdset+1);
467*1da177e4SLinus Torvalds 		ufdset += 2;
468*1da177e4SLinus Torvalds 		n -= 2;
469*1da177e4SLinus Torvalds 	}
470*1da177e4SLinus Torvalds 	if (odd)
471*1da177e4SLinus Torvalds 		__put_user(*fdset, ufdset);
472*1da177e4SLinus Torvalds }
473*1da177e4SLinus Torvalds 
474*1da177e4SLinus Torvalds struct msgbuf32 {
475*1da177e4SLinus Torvalds     int mtype;
476*1da177e4SLinus Torvalds     char mtext[1];
477*1da177e4SLinus Torvalds };
478*1da177e4SLinus Torvalds 
479*1da177e4SLinus Torvalds asmlinkage long sys32_msgsnd(int msqid,
480*1da177e4SLinus Torvalds 				struct msgbuf32 __user *umsgp32,
481*1da177e4SLinus Torvalds 				size_t msgsz, int msgflg)
482*1da177e4SLinus Torvalds {
483*1da177e4SLinus Torvalds 	struct msgbuf *mb;
484*1da177e4SLinus Torvalds 	struct msgbuf32 mb32;
485*1da177e4SLinus Torvalds 	int err;
486*1da177e4SLinus Torvalds 
487*1da177e4SLinus Torvalds 	if ((mb = kmalloc(msgsz + sizeof *mb + 4, GFP_KERNEL)) == NULL)
488*1da177e4SLinus Torvalds 		return -ENOMEM;
489*1da177e4SLinus Torvalds 
490*1da177e4SLinus Torvalds 	err = get_user(mb32.mtype, &umsgp32->mtype);
491*1da177e4SLinus Torvalds 	mb->mtype = mb32.mtype;
492*1da177e4SLinus Torvalds 	err |= copy_from_user(mb->mtext, &umsgp32->mtext, msgsz);
493*1da177e4SLinus Torvalds 
494*1da177e4SLinus Torvalds 	if (err)
495*1da177e4SLinus Torvalds 		err = -EFAULT;
496*1da177e4SLinus Torvalds 	else
497*1da177e4SLinus Torvalds 		KERNEL_SYSCALL(err, sys_msgsnd, msqid, (struct msgbuf __user *)mb, msgsz, msgflg);
498*1da177e4SLinus Torvalds 
499*1da177e4SLinus Torvalds 	kfree(mb);
500*1da177e4SLinus Torvalds 	return err;
501*1da177e4SLinus Torvalds }
502*1da177e4SLinus Torvalds 
503*1da177e4SLinus Torvalds asmlinkage long sys32_msgrcv(int msqid,
504*1da177e4SLinus Torvalds 				struct msgbuf32 __user *umsgp32,
505*1da177e4SLinus Torvalds 				size_t msgsz, long msgtyp, int msgflg)
506*1da177e4SLinus Torvalds {
507*1da177e4SLinus Torvalds 	struct msgbuf *mb;
508*1da177e4SLinus Torvalds 	struct msgbuf32 mb32;
509*1da177e4SLinus Torvalds 	int err, len;
510*1da177e4SLinus Torvalds 
511*1da177e4SLinus Torvalds 	if ((mb = kmalloc(msgsz + sizeof *mb + 4, GFP_KERNEL)) == NULL)
512*1da177e4SLinus Torvalds 		return -ENOMEM;
513*1da177e4SLinus Torvalds 
514*1da177e4SLinus Torvalds 	KERNEL_SYSCALL(err, sys_msgrcv, msqid, (struct msgbuf __user *)mb, msgsz, msgtyp, msgflg);
515*1da177e4SLinus Torvalds 
516*1da177e4SLinus Torvalds 	if (err >= 0) {
517*1da177e4SLinus Torvalds 		len = err;
518*1da177e4SLinus Torvalds 		mb32.mtype = mb->mtype;
519*1da177e4SLinus Torvalds 		err = put_user(mb32.mtype, &umsgp32->mtype);
520*1da177e4SLinus Torvalds 		err |= copy_to_user(&umsgp32->mtext, mb->mtext, len);
521*1da177e4SLinus Torvalds 		if (err)
522*1da177e4SLinus Torvalds 			err = -EFAULT;
523*1da177e4SLinus Torvalds 		else
524*1da177e4SLinus Torvalds 			err = len;
525*1da177e4SLinus Torvalds 	}
526*1da177e4SLinus Torvalds 
527*1da177e4SLinus Torvalds 	kfree(mb);
528*1da177e4SLinus Torvalds 	return err;
529*1da177e4SLinus Torvalds }
530*1da177e4SLinus Torvalds 
531*1da177e4SLinus Torvalds asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, s32 count)
532*1da177e4SLinus Torvalds {
533*1da177e4SLinus Torvalds         mm_segment_t old_fs = get_fs();
534*1da177e4SLinus Torvalds         int ret;
535*1da177e4SLinus Torvalds         off_t of;
536*1da177e4SLinus Torvalds 
537*1da177e4SLinus Torvalds         if (offset && get_user(of, offset))
538*1da177e4SLinus Torvalds                 return -EFAULT;
539*1da177e4SLinus Torvalds 
540*1da177e4SLinus Torvalds         set_fs(KERNEL_DS);
541*1da177e4SLinus Torvalds         ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *)&of : NULL, count);
542*1da177e4SLinus Torvalds         set_fs(old_fs);
543*1da177e4SLinus Torvalds 
544*1da177e4SLinus Torvalds         if (offset && put_user(of, offset))
545*1da177e4SLinus Torvalds                 return -EFAULT;
546*1da177e4SLinus Torvalds 
547*1da177e4SLinus Torvalds         return ret;
548*1da177e4SLinus Torvalds }
549*1da177e4SLinus Torvalds 
550*1da177e4SLinus Torvalds asmlinkage int sys32_sendfile64(int out_fd, int in_fd, compat_loff_t __user *offset, s32 count)
551*1da177e4SLinus Torvalds {
552*1da177e4SLinus Torvalds 	mm_segment_t old_fs = get_fs();
553*1da177e4SLinus Torvalds 	int ret;
554*1da177e4SLinus Torvalds 	loff_t lof;
555*1da177e4SLinus Torvalds 
556*1da177e4SLinus Torvalds 	if (offset && get_user(lof, offset))
557*1da177e4SLinus Torvalds 		return -EFAULT;
558*1da177e4SLinus Torvalds 
559*1da177e4SLinus Torvalds 	set_fs(KERNEL_DS);
560*1da177e4SLinus Torvalds 	ret = sys_sendfile64(out_fd, in_fd, offset ? (loff_t __user *)&lof : NULL, count);
561*1da177e4SLinus Torvalds 	set_fs(old_fs);
562*1da177e4SLinus Torvalds 
563*1da177e4SLinus Torvalds 	if (offset && put_user(lof, offset))
564*1da177e4SLinus Torvalds 		return -EFAULT;
565*1da177e4SLinus Torvalds 
566*1da177e4SLinus Torvalds 	return ret;
567*1da177e4SLinus Torvalds }
568*1da177e4SLinus Torvalds 
569*1da177e4SLinus Torvalds 
570*1da177e4SLinus Torvalds struct timex32 {
571*1da177e4SLinus Torvalds 	unsigned int modes;	/* mode selector */
572*1da177e4SLinus Torvalds 	int offset;		/* time offset (usec) */
573*1da177e4SLinus Torvalds 	int freq;		/* frequency offset (scaled ppm) */
574*1da177e4SLinus Torvalds 	int maxerror;		/* maximum error (usec) */
575*1da177e4SLinus Torvalds 	int esterror;		/* estimated error (usec) */
576*1da177e4SLinus Torvalds 	int status;		/* clock command/status */
577*1da177e4SLinus Torvalds 	int constant;		/* pll time constant */
578*1da177e4SLinus Torvalds 	int precision;		/* clock precision (usec) (read only) */
579*1da177e4SLinus Torvalds 	int tolerance;		/* clock frequency tolerance (ppm)
580*1da177e4SLinus Torvalds 				 * (read only)
581*1da177e4SLinus Torvalds 				 */
582*1da177e4SLinus Torvalds 	struct compat_timeval time;	/* (read only) */
583*1da177e4SLinus Torvalds 	int tick;		/* (modified) usecs between clock ticks */
584*1da177e4SLinus Torvalds 
585*1da177e4SLinus Torvalds 	int ppsfreq;           /* pps frequency (scaled ppm) (ro) */
586*1da177e4SLinus Torvalds 	int jitter;            /* pps jitter (us) (ro) */
587*1da177e4SLinus Torvalds 	int shift;              /* interval duration (s) (shift) (ro) */
588*1da177e4SLinus Torvalds 	int stabil;            /* pps stability (scaled ppm) (ro) */
589*1da177e4SLinus Torvalds 	int jitcnt;            /* jitter limit exceeded (ro) */
590*1da177e4SLinus Torvalds 	int calcnt;            /* calibration intervals (ro) */
591*1da177e4SLinus Torvalds 	int errcnt;            /* calibration errors (ro) */
592*1da177e4SLinus Torvalds 	int stbcnt;            /* stability limit exceeded (ro) */
593*1da177e4SLinus Torvalds 
594*1da177e4SLinus Torvalds 	int  :32; int  :32; int  :32; int  :32;
595*1da177e4SLinus Torvalds 	int  :32; int  :32; int  :32; int  :32;
596*1da177e4SLinus Torvalds 	int  :32; int  :32; int  :32; int  :32;
597*1da177e4SLinus Torvalds };
598*1da177e4SLinus Torvalds 
599*1da177e4SLinus Torvalds asmlinkage long sys32_adjtimex(struct timex32 __user *txc_p32)
600*1da177e4SLinus Torvalds {
601*1da177e4SLinus Torvalds 	struct timex txc;
602*1da177e4SLinus Torvalds 	struct timex32 t32;
603*1da177e4SLinus Torvalds 	int ret;
604*1da177e4SLinus Torvalds 	extern int do_adjtimex(struct timex *txc);
605*1da177e4SLinus Torvalds 
606*1da177e4SLinus Torvalds 	if(copy_from_user(&t32, txc_p32, sizeof(struct timex32)))
607*1da177e4SLinus Torvalds 		return -EFAULT;
608*1da177e4SLinus Torvalds #undef CP
609*1da177e4SLinus Torvalds #define CP(x) txc.x = t32.x
610*1da177e4SLinus Torvalds 	CP(modes); CP(offset); CP(freq); CP(maxerror); CP(esterror);
611*1da177e4SLinus Torvalds 	CP(status); CP(constant); CP(precision); CP(tolerance);
612*1da177e4SLinus Torvalds 	CP(time.tv_sec); CP(time.tv_usec); CP(tick); CP(ppsfreq); CP(jitter);
613*1da177e4SLinus Torvalds 	CP(shift); CP(stabil); CP(jitcnt); CP(calcnt); CP(errcnt);
614*1da177e4SLinus Torvalds 	CP(stbcnt);
615*1da177e4SLinus Torvalds 	ret = do_adjtimex(&txc);
616*1da177e4SLinus Torvalds #undef CP
617*1da177e4SLinus Torvalds #define CP(x) t32.x = txc.x
618*1da177e4SLinus Torvalds 	CP(modes); CP(offset); CP(freq); CP(maxerror); CP(esterror);
619*1da177e4SLinus Torvalds 	CP(status); CP(constant); CP(precision); CP(tolerance);
620*1da177e4SLinus Torvalds 	CP(time.tv_sec); CP(time.tv_usec); CP(tick); CP(ppsfreq); CP(jitter);
621*1da177e4SLinus Torvalds 	CP(shift); CP(stabil); CP(jitcnt); CP(calcnt); CP(errcnt);
622*1da177e4SLinus Torvalds 	CP(stbcnt);
623*1da177e4SLinus Torvalds 	return copy_to_user(txc_p32, &t32, sizeof(struct timex32)) ? -EFAULT : ret;
624*1da177e4SLinus Torvalds }
625*1da177e4SLinus Torvalds 
626*1da177e4SLinus Torvalds 
627*1da177e4SLinus Torvalds struct sysinfo32 {
628*1da177e4SLinus Torvalds 	s32 uptime;
629*1da177e4SLinus Torvalds 	u32 loads[3];
630*1da177e4SLinus Torvalds 	u32 totalram;
631*1da177e4SLinus Torvalds 	u32 freeram;
632*1da177e4SLinus Torvalds 	u32 sharedram;
633*1da177e4SLinus Torvalds 	u32 bufferram;
634*1da177e4SLinus Torvalds 	u32 totalswap;
635*1da177e4SLinus Torvalds 	u32 freeswap;
636*1da177e4SLinus Torvalds 	unsigned short procs;
637*1da177e4SLinus Torvalds 	u32 totalhigh;
638*1da177e4SLinus Torvalds 	u32 freehigh;
639*1da177e4SLinus Torvalds 	u32 mem_unit;
640*1da177e4SLinus Torvalds 	char _f[12];
641*1da177e4SLinus Torvalds };
642*1da177e4SLinus Torvalds 
643*1da177e4SLinus Torvalds /* We used to call sys_sysinfo and translate the result.  But sys_sysinfo
644*1da177e4SLinus Torvalds  * undoes the good work done elsewhere, and rather than undoing the
645*1da177e4SLinus Torvalds  * damage, I decided to just duplicate the code from sys_sysinfo here.
646*1da177e4SLinus Torvalds  */
647*1da177e4SLinus Torvalds 
648*1da177e4SLinus Torvalds asmlinkage int sys32_sysinfo(struct sysinfo32 __user *info)
649*1da177e4SLinus Torvalds {
650*1da177e4SLinus Torvalds 	struct sysinfo val;
651*1da177e4SLinus Torvalds 	int err;
652*1da177e4SLinus Torvalds 	unsigned long seq;
653*1da177e4SLinus Torvalds 
654*1da177e4SLinus Torvalds 	/* We don't need a memset here because we copy the
655*1da177e4SLinus Torvalds 	 * struct to userspace once element at a time.
656*1da177e4SLinus Torvalds 	 */
657*1da177e4SLinus Torvalds 
658*1da177e4SLinus Torvalds 	do {
659*1da177e4SLinus Torvalds 		seq = read_seqbegin(&xtime_lock);
660*1da177e4SLinus Torvalds 		val.uptime = jiffies / HZ;
661*1da177e4SLinus Torvalds 
662*1da177e4SLinus Torvalds 		val.loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT);
663*1da177e4SLinus Torvalds 		val.loads[1] = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT);
664*1da177e4SLinus Torvalds 		val.loads[2] = avenrun[2] << (SI_LOAD_SHIFT - FSHIFT);
665*1da177e4SLinus Torvalds 
666*1da177e4SLinus Torvalds 		val.procs = nr_threads;
667*1da177e4SLinus Torvalds 	} while (read_seqretry(&xtime_lock, seq));
668*1da177e4SLinus Torvalds 
669*1da177e4SLinus Torvalds 
670*1da177e4SLinus Torvalds 	si_meminfo(&val);
671*1da177e4SLinus Torvalds 	si_swapinfo(&val);
672*1da177e4SLinus Torvalds 
673*1da177e4SLinus Torvalds 	err = put_user (val.uptime, &info->uptime);
674*1da177e4SLinus Torvalds 	err |= __put_user (val.loads[0], &info->loads[0]);
675*1da177e4SLinus Torvalds 	err |= __put_user (val.loads[1], &info->loads[1]);
676*1da177e4SLinus Torvalds 	err |= __put_user (val.loads[2], &info->loads[2]);
677*1da177e4SLinus Torvalds 	err |= __put_user (val.totalram, &info->totalram);
678*1da177e4SLinus Torvalds 	err |= __put_user (val.freeram, &info->freeram);
679*1da177e4SLinus Torvalds 	err |= __put_user (val.sharedram, &info->sharedram);
680*1da177e4SLinus Torvalds 	err |= __put_user (val.bufferram, &info->bufferram);
681*1da177e4SLinus Torvalds 	err |= __put_user (val.totalswap, &info->totalswap);
682*1da177e4SLinus Torvalds 	err |= __put_user (val.freeswap, &info->freeswap);
683*1da177e4SLinus Torvalds 	err |= __put_user (val.procs, &info->procs);
684*1da177e4SLinus Torvalds 	err |= __put_user (val.totalhigh, &info->totalhigh);
685*1da177e4SLinus Torvalds 	err |= __put_user (val.freehigh, &info->freehigh);
686*1da177e4SLinus Torvalds 	err |= __put_user (val.mem_unit, &info->mem_unit);
687*1da177e4SLinus Torvalds 	return err ? -EFAULT : 0;
688*1da177e4SLinus Torvalds }
689*1da177e4SLinus Torvalds 
690*1da177e4SLinus Torvalds 
691*1da177e4SLinus Torvalds /* lseek() needs a wrapper because 'offset' can be negative, but the top
692*1da177e4SLinus Torvalds  * half of the argument has been zeroed by syscall.S.
693*1da177e4SLinus Torvalds  */
694*1da177e4SLinus Torvalds 
695*1da177e4SLinus Torvalds asmlinkage int sys32_lseek(unsigned int fd, int offset, unsigned int origin)
696*1da177e4SLinus Torvalds {
697*1da177e4SLinus Torvalds 	return sys_lseek(fd, offset, origin);
698*1da177e4SLinus Torvalds }
699*1da177e4SLinus Torvalds 
700*1da177e4SLinus Torvalds asmlinkage long sys32_semctl(int semid, int semnum, int cmd, union semun arg)
701*1da177e4SLinus Torvalds {
702*1da177e4SLinus Torvalds         union semun u;
703*1da177e4SLinus Torvalds 
704*1da177e4SLinus Torvalds         if (cmd == SETVAL) {
705*1da177e4SLinus Torvalds                 /* Ugh.  arg is a union of int,ptr,ptr,ptr, so is 8 bytes.
706*1da177e4SLinus Torvalds                  * The int should be in the first 4, but our argument
707*1da177e4SLinus Torvalds                  * frobbing has left it in the last 4.
708*1da177e4SLinus Torvalds                  */
709*1da177e4SLinus Torvalds                 u.val = *((int *)&arg + 1);
710*1da177e4SLinus Torvalds                 return sys_semctl (semid, semnum, cmd, u);
711*1da177e4SLinus Torvalds 	}
712*1da177e4SLinus Torvalds 	return sys_semctl (semid, semnum, cmd, arg);
713*1da177e4SLinus Torvalds }
714*1da177e4SLinus Torvalds 
715*1da177e4SLinus Torvalds long sys32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char __user *buf,
716*1da177e4SLinus Torvalds 			  size_t len)
717*1da177e4SLinus Torvalds {
718*1da177e4SLinus Torvalds 	return sys_lookup_dcookie((u64)cookie_high << 32 | cookie_low,
719*1da177e4SLinus Torvalds 				  buf, len);
720*1da177e4SLinus Torvalds }
721