freebsd32_misc.c revision 114987
1/*-
2 * Copyright (c) 2002 Doug Rabson
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/sys/compat/freebsd32/freebsd32_misc.c 114987 2003-05-14 04:10:49Z peter $
27 */
28
29#include "opt_compat.h"
30
31#include <sys/param.h>
32#include <sys/systm.h>
33#include <sys/bus.h>
34#include <sys/exec.h>
35#include <sys/fcntl.h>
36#include <sys/filedesc.h>
37#include <sys/imgact.h>
38#include <sys/kernel.h>
39#include <sys/lock.h>
40#include <sys/malloc.h>
41#include <sys/file.h>		/* Must come after sys/malloc.h */
42#include <sys/mman.h>
43#include <sys/module.h>
44#include <sys/mount.h>
45#include <sys/mutex.h>
46#include <sys/namei.h>
47#include <sys/param.h>
48#include <sys/proc.h>
49#include <sys/reboot.h>
50#include <sys/resource.h>
51#include <sys/resourcevar.h>
52#include <sys/selinfo.h>
53#include <sys/pipe.h>		/* Must come after sys/selinfo.h */
54#include <sys/signal.h>
55#include <sys/signalvar.h>
56#include <sys/socket.h>
57#include <sys/socketvar.h>
58#include <sys/stat.h>
59#include <sys/syscallsubr.h>
60#include <sys/sysctl.h>
61#include <sys/sysent.h>
62#include <sys/sysproto.h>
63#include <sys/systm.h>
64#include <sys/unistd.h>
65#include <sys/user.h>
66#include <sys/utsname.h>
67#include <sys/vnode.h>
68
69#include <vm/vm.h>
70#include <vm/vm_kern.h>
71#include <vm/vm_param.h>
72#include <vm/pmap.h>
73#include <vm/vm_map.h>
74#include <vm/vm_object.h>
75#include <vm/vm_extern.h>
76
77#include <amd64/ia32/ia32_util.h>
78#include <amd64/ia32/ia32.h>
79#include <amd64/ia32/ia32_proto.h>
80
81static const char ia32_emul_path[] = "/compat/ia32";
82/*
83 * [ taken from the linux emulator ]
84 * Search an alternate path before passing pathname arguments on
85 * to system calls. Useful for keeping a separate 'emulation tree'.
86 *
87 * If cflag is set, we check if an attempt can be made to create
88 * the named file, i.e. we check if the directory it should
89 * be in exists.
90 */
91int
92ia32_emul_find(td, sgp, prefix, path, pbuf, cflag)
93	struct thread	*td;
94	caddr_t		*sgp;		/* Pointer to stackgap memory */
95	const char	*prefix;
96	char		*path;
97	char		**pbuf;
98	int		cflag;
99{
100	int			error;
101	size_t			len, sz;
102	char			*buf, *cp, *ptr;
103	struct ucred		*ucred;
104	struct nameidata	nd;
105	struct nameidata	ndroot;
106	struct vattr		vat;
107	struct vattr		vatroot;
108
109	buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
110	*pbuf = path;
111
112	for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++)
113		continue;
114
115	sz = MAXPATHLEN - (ptr - buf);
116
117	/*
118	 * If sgp is not given then the path is already in kernel space
119	 */
120	if (sgp == NULL)
121		error = copystr(path, ptr, sz, &len);
122	else
123		error = copyinstr(path, ptr, sz, &len);
124
125	if (error) {
126		free(buf, M_TEMP);
127		return error;
128	}
129
130	if (*ptr != '/') {
131		free(buf, M_TEMP);
132		return EINVAL;
133	}
134
135	/*
136	 *  We know that there is a / somewhere in this pathname.
137	 *  Search backwards for it, to find the file's parent dir
138	 *  to see if it exists in the alternate tree. If it does,
139	 *  and we want to create a file (cflag is set). We don't
140	 *  need to worry about the root comparison in this case.
141	 */
142
143	if (cflag) {
144		for (cp = &ptr[len] - 1; *cp != '/'; cp--)
145			;
146		*cp = '\0';
147
148		NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
149
150		if ((error = namei(&nd)) != 0) {
151			free(buf, M_TEMP);
152			return error;
153		}
154
155		*cp = '/';
156	} else {
157		NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
158
159		if ((error = namei(&nd)) != 0) {
160			free(buf, M_TEMP);
161			return error;
162		}
163
164		/*
165		 * We now compare the vnode of the ia32_root to the one
166		 * vnode asked. If they resolve to be the same, then we
167		 * ignore the match so that the real root gets used.
168		 * This avoids the problem of traversing "../.." to find the
169		 * root directory and never finding it, because "/" resolves
170		 * to the emulation root directory. This is expensive :-(
171		 */
172		NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, ia32_emul_path,
173		    td);
174
175		if ((error = namei(&ndroot)) != 0) {
176			/* Cannot happen! */
177			free(buf, M_TEMP);
178			vrele(nd.ni_vp);
179			return error;
180		}
181
182		ucred = td->td_ucred;
183		if ((error = VOP_GETATTR(nd.ni_vp, &vat, ucred, td)) != 0) {
184			goto bad;
185		}
186
187		if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, ucred,
188		    td)) != 0) {
189			goto bad;
190		}
191
192		if (vat.va_fsid == vatroot.va_fsid &&
193		    vat.va_fileid == vatroot.va_fileid) {
194			error = ENOENT;
195			goto bad;
196		}
197
198	}
199	if (sgp == NULL)
200		*pbuf = buf;
201	else {
202		sz = &ptr[len] - buf;
203		*pbuf = stackgap_alloc(sgp, sz + 1);
204		error = copyout(buf, *pbuf, sz);
205		free(buf, M_TEMP);
206	}
207
208	vrele(nd.ni_vp);
209	if (!cflag)
210		vrele(ndroot.ni_vp);
211
212	return error;
213
214bad:
215	vrele(ndroot.ni_vp);
216	vrele(nd.ni_vp);
217	free(buf, M_TEMP);
218	return error;
219}
220
221int
222ia32_open(struct thread *td, struct ia32_open_args *uap)
223{
224	caddr_t sg;
225
226	sg = stackgap_init();
227	CHECKALTEXIST(td, &sg, uap->path);
228
229	return open(td, (struct open_args *) uap);
230}
231
232int
233ia32_wait4(struct thread *td, struct ia32_wait4_args *uap)
234{
235	int error;
236	caddr_t sg;
237	struct rusage32 *rusage32, ru32;
238	struct rusage *rusage = NULL, ru;
239
240	rusage32 = uap->rusage;
241	if (rusage32) {
242		sg = stackgap_init();
243		rusage = stackgap_alloc(&sg, sizeof(struct rusage));
244		uap->rusage = (struct rusage32 *)rusage;
245	}
246	error = wait4(td, (struct wait_args *)uap);
247	if (error)
248		return (error);
249	if (rusage32 && (error = copyin(rusage, &ru, sizeof(ru)) == 0)) {
250		TV_CP(ru, ru32, ru_utime);
251		TV_CP(ru, ru32, ru_stime);
252		CP(ru, ru32, ru_maxrss);
253		CP(ru, ru32, ru_ixrss);
254		CP(ru, ru32, ru_idrss);
255		CP(ru, ru32, ru_isrss);
256		CP(ru, ru32, ru_minflt);
257		CP(ru, ru32, ru_majflt);
258		CP(ru, ru32, ru_nswap);
259		CP(ru, ru32, ru_inblock);
260		CP(ru, ru32, ru_oublock);
261		CP(ru, ru32, ru_msgsnd);
262		CP(ru, ru32, ru_msgrcv);
263		CP(ru, ru32, ru_nsignals);
264		CP(ru, ru32, ru_nvcsw);
265		CP(ru, ru32, ru_nivcsw);
266		error = copyout(&ru32, rusage32, sizeof(ru32));
267	}
268	return (error);
269}
270
271static void
272copy_statfs(struct statfs *in, struct statfs32 *out)
273{
274	CP(*in, *out, f_bsize);
275	CP(*in, *out, f_iosize);
276	CP(*in, *out, f_blocks);
277	CP(*in, *out, f_bfree);
278	CP(*in, *out, f_bavail);
279	CP(*in, *out, f_files);
280	CP(*in, *out, f_ffree);
281	CP(*in, *out, f_fsid);
282	CP(*in, *out, f_owner);
283	CP(*in, *out, f_type);
284	CP(*in, *out, f_flags);
285	CP(*in, *out, f_flags);
286	CP(*in, *out, f_syncwrites);
287	CP(*in, *out, f_asyncwrites);
288	bcopy(in->f_fstypename,
289	      out->f_fstypename, MFSNAMELEN);
290	bcopy(in->f_mntonname,
291	      out->f_mntonname, MNAMELEN);
292	CP(*in, *out, f_syncreads);
293	CP(*in, *out, f_asyncreads);
294	bcopy(in->f_mntfromname,
295	      out->f_mntfromname, MNAMELEN);
296}
297
298int
299ia32_getfsstat(struct thread *td, struct ia32_getfsstat_args *uap)
300{
301	int error;
302	caddr_t sg;
303	struct statfs32 *sp32, stat32;
304	struct statfs *sp = NULL, stat;
305	int maxcount, count, i;
306
307	sp32 = uap->buf;
308	maxcount = uap->bufsize / sizeof(struct statfs32);
309
310	if (sp32) {
311		sg = stackgap_init();
312		sp = stackgap_alloc(&sg, sizeof(struct statfs) * maxcount);
313		uap->buf = (struct statfs32 *)sp;
314	}
315	error = getfsstat(td, (struct getfsstat_args *) uap);
316	if (sp32 && !error) {
317		count = td->td_retval[0];
318		for (i = 0; i < count; i++) {
319			error = copyin(&sp[i], &stat, sizeof(stat));
320			if (error)
321				return (error);
322			copy_statfs(&stat, &stat32);
323			error = copyout(&stat32, &sp32[i], sizeof(stat32));
324			if (error)
325				return (error);
326		}
327	}
328	return (error);
329}
330
331int
332ia32_access(struct thread *td, struct ia32_access_args *uap)
333{
334	caddr_t sg;
335
336	sg = stackgap_init();
337	CHECKALTEXIST(td, &sg, uap->path);
338
339	return access(td, (struct access_args *)uap);
340}
341
342int
343ia32_chflags(struct thread *td, struct ia32_chflags_args *uap)
344{
345	caddr_t sg;
346
347	sg = stackgap_init();
348	CHECKALTEXIST(td, &sg, uap->path);
349
350	return chflags(td, (struct chflags_args *)uap);
351}
352
353struct sigaltstack32 {
354	u_int32_t	ss_sp;
355	u_int32_t	ss_size;
356	int		ss_flags;
357};
358
359int
360ia32_sigaltstack(struct thread *td, struct ia32_sigaltstack_args *uap)
361{
362	struct sigaltstack32 s32;
363	struct sigaltstack ss, oss, *ssp;
364	int error;
365
366	if (uap->ss != NULL) {
367		error = copyin(uap->ss, &s32, sizeof(s32));
368		if (error)
369			return (error);
370		PTRIN_CP(s32, ss, ss_sp);
371		CP(s32, ss, ss_size);
372		CP(s32, ss, ss_flags);
373		ssp = &ss;
374	} else
375		ssp = NULL;
376	error = kern_sigaltstack(td, ssp, &oss);
377	if (error == 0 && uap->oss != NULL) {
378		PTROUT_CP(oss, s32, ss_sp);
379		CP(oss, s32, ss_size);
380		CP(oss, s32, ss_flags);
381		error = copyout(&s32, uap->oss, sizeof(s32));
382	}
383	return (error);
384}
385
386int
387ia32_execve(struct thread *td, struct ia32_execve_args *uap)
388{
389	int error;
390	caddr_t sg;
391	struct execve_args ap;
392	u_int32_t *p32, arg;
393	char **p;
394	int count;
395
396	sg = stackgap_init();
397	CHECKALTEXIST(td, &sg, uap->fname);
398	ap.fname = uap->fname;
399
400	if (uap->argv) {
401		count = 0;
402		p32 = uap->argv;
403		do {
404			error = copyin(p32++, &arg, sizeof(arg));
405			if (error)
406				return error;
407			count++;
408		} while (arg != 0);
409		p = stackgap_alloc(&sg, count * sizeof(char *));
410		ap.argv = p;
411		p32 = uap->argv;
412		do {
413			error = copyin(p32++, &arg, sizeof(arg));
414			if (error)
415				return error;
416			*p++ = PTRIN(arg);
417		} while (arg != 0);
418	}
419	if (uap->envv) {
420		count = 0;
421		p32 = uap->envv;
422		do {
423			error = copyin(p32++, &arg, sizeof(arg));
424			if (error)
425				return error;
426			count++;
427		} while (arg != 0);
428		p = stackgap_alloc(&sg, count * sizeof(char *));
429		ap.envv = p;
430		p32 = uap->envv;
431		do {
432			error = copyin(p32++, &arg, sizeof(arg));
433			if (error)
434				return error;
435			*p++ = PTRIN(arg);
436		} while (arg != 0);
437	}
438
439	return execve(td, &ap);
440}
441
442#ifdef __ia64__
443static int
444ia32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
445		  int prot, int fd, off_t pos)
446{
447	vm_map_t map;
448	vm_map_entry_t entry;
449	int rv;
450
451	map = &td->td_proc->p_vmspace->vm_map;
452	if (fd != -1)
453		prot |= VM_PROT_WRITE;
454
455	if (vm_map_lookup_entry(map, start, &entry)) {
456		if ((entry->protection & prot) != prot) {
457			rv = vm_map_protect(map,
458					    trunc_page(start),
459					    round_page(end),
460					    entry->protection | prot,
461					    FALSE);
462			if (rv != KERN_SUCCESS)
463				return (EINVAL);
464		}
465	} else {
466		vm_offset_t addr = trunc_page(start);
467		rv = vm_map_find(map, 0, 0,
468				 &addr, PAGE_SIZE, FALSE, prot,
469				 VM_PROT_ALL, 0);
470		if (rv != KERN_SUCCESS)
471			return (EINVAL);
472	}
473
474	if (fd != -1) {
475		struct pread_args r;
476		r.fd = fd;
477		r.buf = (void *) start;
478		r.nbyte = end - start;
479		r.offset = pos;
480		return (pread(td, &r));
481	} else {
482		while (start < end) {
483			subyte((void *) start, 0);
484			start++;
485		}
486		return (0);
487	}
488}
489#endif
490
491int
492ia32_mmap(struct thread *td, struct ia32_mmap_args *uap)
493{
494	struct mmap_args ap;
495	vm_offset_t addr = (vm_offset_t) uap->addr;
496	vm_size_t len	 = uap->len;
497	int prot	 = uap->prot;
498	int flags	 = uap->flags;
499	int fd		 = uap->fd;
500	off_t pos	 = (uap->poslo
501			    | ((off_t)uap->poshi << 32));
502#ifdef __ia64__
503	vm_size_t pageoff;
504	int error;
505
506	/*
507	 * Attempt to handle page size hassles.
508	 */
509	pageoff = (pos & PAGE_MASK);
510	if (flags & MAP_FIXED) {
511		vm_offset_t start, end;
512		start = addr;
513		end = addr + len;
514
515		if (start != trunc_page(start)) {
516			error = ia32_mmap_partial(td, start, round_page(start),
517						  prot, fd, pos);
518			if (fd != -1)
519				pos += round_page(start) - start;
520			start = round_page(start);
521		}
522		if (end != round_page(end)) {
523			vm_offset_t t = trunc_page(end);
524			error = ia32_mmap_partial(td, t, end,
525						  prot, fd,
526						  pos + t - start);
527			end = trunc_page(end);
528		}
529		if (end > start && fd != -1 && (pos & PAGE_MASK)) {
530			/*
531			 * We can't map this region at all. The specified
532			 * address doesn't have the same alignment as the file
533			 * position. Fake the mapping by simply reading the
534			 * entire region into memory. First we need to make
535			 * sure the region exists.
536			 */
537			vm_map_t map;
538			struct pread_args r;
539			int rv;
540
541			prot |= VM_PROT_WRITE;
542			map = &td->td_proc->p_vmspace->vm_map;
543			rv = vm_map_remove(map, start, end);
544			if (rv != KERN_SUCCESS)
545				return (EINVAL);
546			rv = vm_map_find(map, 0, 0,
547					 &start, end - start, FALSE,
548					 prot, VM_PROT_ALL, 0);
549			if (rv != KERN_SUCCESS)
550				return (EINVAL);
551			r.fd = fd;
552			r.buf = (void *) start;
553			r.nbyte = end - start;
554			r.offset = pos;
555			error = pread(td, &r);
556			if (error)
557				return (error);
558
559			td->td_retval[0] = addr;
560			return (0);
561		}
562		if (end == start) {
563			/*
564			 * After dealing with the ragged ends, there
565			 * might be none left.
566			 */
567			td->td_retval[0] = addr;
568			return (0);
569		}
570		addr = start;
571		len = end - start;
572	}
573#endif
574
575	ap.addr = (void *) addr;
576	ap.len = len;
577	ap.prot = prot;
578	ap.flags = flags;
579	ap.fd = fd;
580	ap.pos = pos;
581
582	return (mmap(td, &ap));
583}
584
585struct itimerval32 {
586	struct timeval32 it_interval;
587	struct timeval32 it_value;
588};
589
590int
591ia32_setitimer(struct thread *td, struct ia32_setitimer_args *uap)
592{
593	int error;
594	caddr_t sg;
595	struct itimerval32 *p32, *op32, s32;
596	struct itimerval *p = NULL, *op = NULL, s;
597
598	p32 = uap->itv;
599	if (p32) {
600		sg = stackgap_init();
601		p = stackgap_alloc(&sg, sizeof(struct itimerval));
602		uap->itv = (struct itimerval32 *)p;
603		error = copyin(p32, &s32, sizeof(s32));
604		if (error)
605			return (error);
606		TV_CP(s32, s, it_interval);
607		TV_CP(s32, s, it_value);
608		error = copyout(&s, p, sizeof(s));
609		if (error)
610			return (error);
611	}
612	op32 = uap->oitv;
613	if (op32) {
614		sg = stackgap_init();
615		op = stackgap_alloc(&sg, sizeof(struct itimerval));
616		uap->oitv = (struct itimerval32 *)op;
617	}
618	error = setitimer(td, (struct setitimer_args *) uap);
619	if (error)
620		return (error);
621	if (op32) {
622		error = copyin(op, &s, sizeof(s));
623		if (error)
624			return (error);
625		TV_CP(s, s32, it_interval);
626		TV_CP(s, s32, it_value);
627		error = copyout(&s32, op32, sizeof(s32));
628	}
629	return (error);
630}
631
632int
633ia32_select(struct thread *td, struct ia32_select_args *uap)
634{
635	int error;
636	caddr_t sg;
637	struct timeval32 *p32, s32;
638	struct timeval *p = NULL, s;
639
640	p32 = uap->tv;
641	if (p32) {
642		sg = stackgap_init();
643		p = stackgap_alloc(&sg, sizeof(struct timeval));
644		uap->tv = (struct timeval32 *)p;
645		error = copyin(p32, &s32, sizeof(s32));
646		if (error)
647			return (error);
648		CP(s32, s, tv_sec);
649		CP(s32, s, tv_usec);
650		error = copyout(&s, p, sizeof(s));
651		if (error)
652			return (error);
653	}
654	/*
655	 * XXX big-endian needs to convert the fd_sets too.
656	 */
657	return (select(td, (struct select_args *) uap));
658}
659
660struct kevent32 {
661	u_int32_t	ident;		/* identifier for this event */
662	short		filter;		/* filter for event */
663	u_short		flags;
664	u_int		fflags;
665	int32_t		data;
666	u_int32_t	udata;		/* opaque user data identifier */
667};
668
669int
670ia32_kevent(struct thread *td, struct ia32_kevent_args *uap)
671{
672	int error;
673	caddr_t sg;
674	struct timespec32 ts32;
675	struct timespec ts;
676	struct kevent32 ks32;
677	struct kevent *ks;
678	struct kevent_args a;
679	int i;
680
681	sg = stackgap_init();
682
683	a.fd = uap->fd;
684	a.changelist = uap->changelist;
685	a.nchanges = uap->nchanges;
686	a.eventlist = uap->eventlist;
687	a.nevents = uap->nevents;
688	a.timeout = NULL;
689
690	if (uap->timeout) {
691		a.timeout = stackgap_alloc(&sg, sizeof(struct timespec));
692		error = copyin(uap->timeout, &ts32, sizeof(ts32));
693		if (error)
694			return (error);
695		CP(ts32, ts, tv_sec);
696		CP(ts32, ts, tv_nsec);
697		error = copyout(&ts, (void *)(uintptr_t)a.timeout, sizeof(ts));
698		if (error)
699			return (error);
700	}
701	if (uap->changelist) {
702		a.changelist = (struct kevent *)stackgap_alloc(&sg, uap->nchanges * sizeof(struct kevent));
703		for (i = 0; i < uap->nchanges; i++) {
704			error = copyin(&uap->changelist[i], &ks32, sizeof(ks32));
705			if (error)
706				return (error);
707			ks = (struct kevent *)(uintptr_t)&a.changelist[i];
708			CP(ks32, *ks, ident);
709			CP(ks32, *ks, filter);
710			CP(ks32, *ks, flags);
711			CP(ks32, *ks, fflags);
712			CP(ks32, *ks, data);
713			PTRIN_CP(ks32, *ks, udata);
714		}
715	}
716	if (uap->eventlist) {
717		a.eventlist = stackgap_alloc(&sg, uap->nevents * sizeof(struct kevent));
718	}
719	error = kevent(td, &a);
720	if (uap->eventlist && error > 0) {
721		for (i = 0; i < error; i++) {
722			ks = &a.eventlist[i];
723			CP(*ks, ks32, ident);
724			CP(*ks, ks32, filter);
725			CP(*ks, ks32, flags);
726			CP(*ks, ks32, fflags);
727			CP(*ks, ks32, data);
728			PTROUT_CP(*ks, ks32, udata);
729			error = copyout(&ks32, &uap->eventlist[i], sizeof(ks32));
730			if (error)
731				return (error);
732		}
733	}
734	return error;
735}
736
737int
738ia32_gettimeofday(struct thread *td, struct ia32_gettimeofday_args *uap)
739{
740	int error;
741	caddr_t sg;
742	struct timeval32 *p32, s32;
743	struct timeval *p = NULL, s;
744
745	p32 = uap->tp;
746	if (p32) {
747		sg = stackgap_init();
748		p = stackgap_alloc(&sg, sizeof(struct timeval));
749		uap->tp = (struct timeval32 *)p;
750	}
751	error = gettimeofday(td, (struct gettimeofday_args *) uap);
752	if (error)
753		return (error);
754	if (p32) {
755		error = copyin(p, &s, sizeof(s));
756		if (error)
757			return (error);
758		CP(s, s32, tv_sec);
759		CP(s, s32, tv_usec);
760		error = copyout(&s32, p32, sizeof(s32));
761		if (error)
762			return (error);
763	}
764	return (error);
765}
766
767int
768ia32_getrusage(struct thread *td, struct ia32_getrusage_args *uap)
769{
770	int error;
771	caddr_t sg;
772	struct rusage32 *p32, s32;
773	struct rusage *p = NULL, s;
774
775	p32 = uap->rusage;
776	if (p32) {
777		sg = stackgap_init();
778		p = stackgap_alloc(&sg, sizeof(struct rusage));
779		uap->rusage = (struct rusage32 *)p;
780	}
781	error = getrusage(td, (struct getrusage_args *) uap);
782	if (error)
783		return (error);
784	if (p32) {
785		error = copyin(p, &s, sizeof(s));
786		if (error)
787			return (error);
788		TV_CP(s, s32, ru_utime);
789		TV_CP(s, s32, ru_stime);
790		CP(s, s32, ru_maxrss);
791		CP(s, s32, ru_ixrss);
792		CP(s, s32, ru_idrss);
793		CP(s, s32, ru_isrss);
794		CP(s, s32, ru_minflt);
795		CP(s, s32, ru_majflt);
796		CP(s, s32, ru_nswap);
797		CP(s, s32, ru_inblock);
798		CP(s, s32, ru_oublock);
799		CP(s, s32, ru_msgsnd);
800		CP(s, s32, ru_msgrcv);
801		CP(s, s32, ru_nsignals);
802		CP(s, s32, ru_nvcsw);
803		CP(s, s32, ru_nivcsw);
804		error = copyout(&s32, p32, sizeof(s32));
805	}
806	return (error);
807}
808
809struct iovec32 {
810	u_int32_t iov_base;
811	int	iov_len;
812};
813#define	STACKGAPLEN	400
814
815int
816ia32_readv(struct thread *td, struct ia32_readv_args *uap)
817{
818	int error, osize, nsize, i;
819	caddr_t sg;
820	struct readv_args /* {
821		syscallarg(int) fd;
822		syscallarg(struct iovec *) iovp;
823		syscallarg(u_int) iovcnt;
824	} */ a;
825	struct iovec32 *oio;
826	struct iovec *nio;
827
828	sg = stackgap_init();
829
830	if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
831		return (EINVAL);
832
833	osize = uap->iovcnt * sizeof (struct iovec32);
834	nsize = uap->iovcnt * sizeof (struct iovec);
835
836	oio = malloc(osize, M_TEMP, M_WAITOK);
837	nio = malloc(nsize, M_TEMP, M_WAITOK);
838
839	error = 0;
840	if ((error = copyin(uap->iovp, oio, osize)))
841		goto punt;
842	for (i = 0; i < uap->iovcnt; i++) {
843		nio[i].iov_base = PTRIN(oio[i].iov_base);
844		nio[i].iov_len = oio[i].iov_len;
845	}
846
847	a.fd = uap->fd;
848	a.iovp = stackgap_alloc(&sg, nsize);
849	a.iovcnt = uap->iovcnt;
850
851	if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
852		goto punt;
853	error = readv(td, &a);
854
855punt:
856	free(oio, M_TEMP);
857	free(nio, M_TEMP);
858	return (error);
859}
860
861int
862ia32_writev(struct thread *td, struct ia32_writev_args *uap)
863{
864	int error, i, nsize, osize;
865	caddr_t sg;
866	struct writev_args /* {
867		syscallarg(int) fd;
868		syscallarg(struct iovec *) iovp;
869		syscallarg(u_int) iovcnt;
870	} */ a;
871	struct iovec32 *oio;
872	struct iovec *nio;
873
874	sg = stackgap_init();
875
876	if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
877		return (EINVAL);
878
879	osize = uap->iovcnt * sizeof (struct iovec32);
880	nsize = uap->iovcnt * sizeof (struct iovec);
881
882	oio = malloc(osize, M_TEMP, M_WAITOK);
883	nio = malloc(nsize, M_TEMP, M_WAITOK);
884
885	error = 0;
886	if ((error = copyin(uap->iovp, oio, osize)))
887		goto punt;
888	for (i = 0; i < uap->iovcnt; i++) {
889		nio[i].iov_base = PTRIN(oio[i].iov_base);
890		nio[i].iov_len = oio[i].iov_len;
891	}
892
893	a.fd = uap->fd;
894	a.iovp = stackgap_alloc(&sg, nsize);
895	a.iovcnt = uap->iovcnt;
896
897	if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
898		goto punt;
899	error = writev(td, &a);
900
901punt:
902	free(oio, M_TEMP);
903	free(nio, M_TEMP);
904	return (error);
905}
906
907int
908ia32_settimeofday(struct thread *td, struct ia32_settimeofday_args *uap)
909{
910	int error;
911	caddr_t sg;
912	struct timeval32 *p32, s32;
913	struct timeval *p = NULL, s;
914
915	p32 = uap->tv;
916	if (p32) {
917		sg = stackgap_init();
918		p = stackgap_alloc(&sg, sizeof(struct timeval));
919		uap->tv = (struct timeval32 *)p;
920		error = copyin(p32, &s32, sizeof(s32));
921		if (error)
922			return (error);
923		CP(s32, s, tv_sec);
924		CP(s32, s, tv_usec);
925		error = copyout(&s, p, sizeof(s));
926		if (error)
927			return (error);
928	}
929	return (settimeofday(td, (struct settimeofday_args *) uap));
930}
931
932int
933ia32_utimes(struct thread *td, struct ia32_utimes_args *uap)
934{
935	int error;
936	caddr_t sg;
937	struct timeval32 *p32, s32[2];
938	struct timeval *p = NULL, s[2];
939
940	p32 = uap->tptr;
941	if (p32) {
942		sg = stackgap_init();
943		p = stackgap_alloc(&sg, 2*sizeof(struct timeval));
944		uap->tptr = (struct timeval32 *)p;
945		error = copyin(p32, s32, sizeof(s32));
946		if (error)
947			return (error);
948		CP(s32[0], s[0], tv_sec);
949		CP(s32[0], s[0], tv_usec);
950		CP(s32[1], s[1], tv_sec);
951		CP(s32[1], s[1], tv_usec);
952		error = copyout(s, p, sizeof(s));
953		if (error)
954			return (error);
955	}
956	return (utimes(td, (struct utimes_args *) uap));
957}
958
959int
960ia32_adjtime(struct thread *td, struct ia32_adjtime_args *uap)
961{
962	int error;
963	caddr_t sg;
964	struct timeval32 *p32, *op32, s32;
965	struct timeval *p = NULL, *op = NULL, s;
966
967	p32 = uap->delta;
968	if (p32) {
969		sg = stackgap_init();
970		p = stackgap_alloc(&sg, sizeof(struct timeval));
971		uap->delta = (struct timeval32 *)p;
972		error = copyin(p32, &s32, sizeof(s32));
973		if (error)
974			return (error);
975		CP(s32, s, tv_sec);
976		CP(s32, s, tv_usec);
977		error = copyout(&s, p, sizeof(s));
978		if (error)
979			return (error);
980	}
981	op32 = uap->olddelta;
982	if (op32) {
983		sg = stackgap_init();
984		op = stackgap_alloc(&sg, sizeof(struct timeval));
985		uap->olddelta = (struct timeval32 *)op;
986	}
987	error = utimes(td, (struct utimes_args *) uap);
988	if (error)
989		return error;
990	if (op32) {
991		error = copyin(op, &s, sizeof(s));
992		if (error)
993			return (error);
994		CP(s, s32, tv_sec);
995		CP(s, s32, tv_usec);
996		error = copyout(&s32, op32, sizeof(s32));
997	}
998	return (error);
999}
1000
1001int
1002ia32_statfs(struct thread *td, struct ia32_statfs_args *uap)
1003{
1004	int error;
1005	caddr_t sg;
1006	struct statfs32 *p32, s32;
1007	struct statfs *p = NULL, s;
1008
1009	p32 = uap->buf;
1010	if (p32) {
1011		sg = stackgap_init();
1012		p = stackgap_alloc(&sg, sizeof(struct statfs));
1013		uap->buf = (struct statfs32 *)p;
1014	}
1015	error = statfs(td, (struct statfs_args *) uap);
1016	if (error)
1017		return (error);
1018	if (p32) {
1019		error = copyin(p, &s, sizeof(s));
1020		if (error)
1021			return (error);
1022		copy_statfs(&s, &s32);
1023		error = copyout(&s32, p32, sizeof(s32));
1024	}
1025	return (error);
1026}
1027
1028int
1029ia32_fstatfs(struct thread *td, struct ia32_fstatfs_args *uap)
1030{
1031	int error;
1032	caddr_t sg;
1033	struct statfs32 *p32, s32;
1034	struct statfs *p = NULL, s;
1035
1036	p32 = uap->buf;
1037	if (p32) {
1038		sg = stackgap_init();
1039		p = stackgap_alloc(&sg, sizeof(struct statfs));
1040		uap->buf = (struct statfs32 *)p;
1041	}
1042	error = fstatfs(td, (struct fstatfs_args *) uap);
1043	if (error)
1044		return (error);
1045	if (p32) {
1046		error = copyin(p, &s, sizeof(s));
1047		if (error)
1048			return (error);
1049		copy_statfs(&s, &s32);
1050		error = copyout(&s32, p32, sizeof(s32));
1051	}
1052	return (error);
1053}
1054
1055int
1056ia32_semsys(struct thread *td, struct ia32_semsys_args *uap)
1057{
1058	/*
1059	 * Vector through to semsys if it is loaded.
1060	 */
1061	return sysent[169].sy_call(td, uap);
1062}
1063
1064int
1065ia32_msgsys(struct thread *td, struct ia32_msgsys_args *uap)
1066{
1067	/*
1068	 * Vector through to msgsys if it is loaded.
1069	 */
1070	return sysent[170].sy_call(td, uap);
1071}
1072
1073int
1074ia32_shmsys(struct thread *td, struct ia32_shmsys_args *uap)
1075{
1076	/*
1077	 * Vector through to shmsys if it is loaded.
1078	 */
1079	return sysent[171].sy_call(td, uap);
1080}
1081
1082int
1083ia32_pread(struct thread *td, struct ia32_pread_args *uap)
1084{
1085	struct pread_args ap;
1086
1087	ap.fd = uap->fd;
1088	ap.buf = uap->buf;
1089	ap.nbyte = uap->nbyte;
1090	ap.offset = (uap->offsetlo
1091			      | ((off_t)uap->offsethi << 32));
1092	return (pread(td, &ap));
1093}
1094
1095int
1096ia32_pwrite(struct thread *td, struct ia32_pwrite_args *uap)
1097{
1098	struct pwrite_args ap;
1099
1100	ap.fd = uap->fd;
1101	ap.buf = uap->buf;
1102	ap.nbyte = uap->nbyte;
1103	ap.offset = (uap->offsetlo
1104			      | ((off_t)uap->offsethi << 32));
1105	return (pwrite(td, &ap));
1106}
1107
1108int
1109ia32_lseek(struct thread *td, struct ia32_lseek_args *uap)
1110{
1111	int error;
1112	struct lseek_args ap;
1113	off_t pos;
1114
1115	ap.fd = uap->fd;
1116	ap.offset = (uap->offsetlo
1117			      | ((off_t)uap->offsethi << 32));
1118	ap.whence = uap->whence;
1119	error = lseek(td, &ap);
1120	/* Expand the quad return into two parts for eax and edx */
1121	pos = *(off_t *)(td->td_retval);
1122	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
1123	td->td_retval[1] = pos >> 32;		/* %edx */
1124	return error;
1125}
1126
1127int
1128ia32_truncate(struct thread *td, struct ia32_truncate_args *uap)
1129{
1130	struct truncate_args ap;
1131
1132	ap.path = uap->path;
1133	ap.length = (uap->lengthlo
1134			      | ((off_t)uap->lengthhi << 32));
1135	return (truncate(td, &ap));
1136}
1137
1138int
1139ia32_ftruncate(struct thread *td, struct ia32_ftruncate_args *uap)
1140{
1141	struct ftruncate_args ap;
1142
1143	ap.fd = uap->fd;
1144	ap.length = (uap->lengthlo
1145			      | ((off_t)uap->lengthhi << 32));
1146	return (ftruncate(td, &ap));
1147}
1148
1149#ifdef COMPAT_FREEBSD4
1150int
1151freebsd4_ia32_sendfile(struct thread *td,
1152    struct freebsd4_ia32_sendfile_args *uap)
1153{
1154	struct freebsd4_sendfile_args ap;
1155
1156	ap.fd = uap->fd;
1157	ap.s = uap->s;
1158	ap.offset = (uap->offsetlo
1159			      | ((off_t)uap->offsethi << 32));
1160	ap.nbytes = uap->nbytes;	/* XXX check */
1161	ap.hdtr = uap->hdtr;		/* XXX check */
1162	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1163	ap.flags = uap->flags;
1164	return (freebsd4_sendfile(td, &ap));
1165}
1166#endif
1167
1168int
1169ia32_sendfile(struct thread *td, struct ia32_sendfile_args *uap)
1170{
1171	struct sendfile_args ap;
1172
1173	ap.fd = uap->fd;
1174	ap.s = uap->s;
1175	ap.offset = (uap->offsetlo
1176			      | ((off_t)uap->offsethi << 32));
1177	ap.nbytes = uap->nbytes;	/* XXX check */
1178	ap.hdtr = uap->hdtr;		/* XXX check */
1179	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1180	ap.flags = uap->flags;
1181	return (sendfile(td, &ap));
1182}
1183
1184struct stat32 {
1185	udev_t	st_dev;
1186	ino_t	st_ino;
1187	mode_t	st_mode;
1188	nlink_t	st_nlink;
1189	uid_t	st_uid;
1190	gid_t	st_gid;
1191	udev_t	st_rdev;
1192	struct timespec32 st_atimespec;
1193	struct timespec32 st_mtimespec;
1194	struct timespec32 st_ctimespec;
1195	off_t	st_size;
1196	int64_t	st_blocks;
1197	u_int32_t st_blksize;
1198	u_int32_t st_flags;
1199	u_int32_t st_gen;
1200};
1201
1202static void
1203copy_stat( struct stat *in, struct stat32 *out)
1204{
1205	CP(*in, *out, st_dev);
1206	CP(*in, *out, st_ino);
1207	CP(*in, *out, st_mode);
1208	CP(*in, *out, st_nlink);
1209	CP(*in, *out, st_uid);
1210	CP(*in, *out, st_gid);
1211	CP(*in, *out, st_rdev);
1212	TS_CP(*in, *out, st_atimespec);
1213	TS_CP(*in, *out, st_mtimespec);
1214	TS_CP(*in, *out, st_ctimespec);
1215	CP(*in, *out, st_size);
1216	CP(*in, *out, st_blocks);
1217	CP(*in, *out, st_blksize);
1218	CP(*in, *out, st_flags);
1219	CP(*in, *out, st_gen);
1220}
1221
1222int
1223ia32_stat(struct thread *td, struct ia32_stat_args *uap)
1224{
1225	int error;
1226	caddr_t sg;
1227	struct stat32 *p32, s32;
1228	struct stat *p = NULL, s;
1229
1230	p32 = uap->ub;
1231	if (p32) {
1232		sg = stackgap_init();
1233		p = stackgap_alloc(&sg, sizeof(struct stat));
1234		uap->ub = (struct stat32 *)p;
1235	}
1236	error = stat(td, (struct stat_args *) uap);
1237	if (error)
1238		return (error);
1239	if (p32) {
1240		error = copyin(p, &s, sizeof(s));
1241		if (error)
1242			return (error);
1243		copy_stat(&s, &s32);
1244		error = copyout(&s32, p32, sizeof(s32));
1245	}
1246	return (error);
1247}
1248
1249int
1250ia32_fstat(struct thread *td, struct ia32_fstat_args *uap)
1251{
1252	int error;
1253	caddr_t sg;
1254	struct stat32 *p32, s32;
1255	struct stat *p = NULL, s;
1256
1257	p32 = uap->ub;
1258	if (p32) {
1259		sg = stackgap_init();
1260		p = stackgap_alloc(&sg, sizeof(struct stat));
1261		uap->ub = (struct stat32 *)p;
1262	}
1263	error = fstat(td, (struct fstat_args *) uap);
1264	if (error)
1265		return (error);
1266	if (p32) {
1267		error = copyin(p, &s, sizeof(s));
1268		if (error)
1269			return (error);
1270		copy_stat(&s, &s32);
1271		error = copyout(&s32, p32, sizeof(s32));
1272	}
1273	return (error);
1274}
1275
1276int
1277ia32_lstat(struct thread *td, struct ia32_lstat_args *uap)
1278{
1279	int error;
1280	caddr_t sg;
1281	struct stat32 *p32, s32;
1282	struct stat *p = NULL, s;
1283
1284	p32 = uap->ub;
1285	if (p32) {
1286		sg = stackgap_init();
1287		p = stackgap_alloc(&sg, sizeof(struct stat));
1288		uap->ub = (struct stat32 *)p;
1289	}
1290	error = lstat(td, (struct lstat_args *) uap);
1291	if (error)
1292		return (error);
1293	if (p32) {
1294		error = copyin(p, &s, sizeof(s));
1295		if (error)
1296			return (error);
1297		copy_stat(&s, &s32);
1298		error = copyout(&s32, p32, sizeof(s32));
1299	}
1300	return (error);
1301}
1302
1303/*
1304 * MPSAFE
1305 */
1306int
1307ia32_sysctl(struct thread *td, struct ia32_sysctl_args *uap)
1308{
1309	int error, name[CTL_MAXNAME];
1310	size_t j, oldlen;
1311
1312	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1313		return (EINVAL);
1314
1315 	error = copyin(uap->name, &name, uap->namelen * sizeof(int));
1316 	if (error)
1317		return (error);
1318
1319	mtx_lock(&Giant);
1320
1321	if (uap->oldlenp)
1322		oldlen = fuword32(uap->oldlenp);
1323	else
1324		oldlen = 0;
1325	error = userland_sysctl(td, name, uap->namelen,
1326		uap->old, &oldlen, 1,
1327		uap->new, uap->newlen, &j);
1328	if (error && error != ENOMEM)
1329		goto done2;
1330	if (uap->oldlenp) {
1331		suword32(uap->oldlenp, j);
1332	}
1333done2:
1334	mtx_unlock(&Giant);
1335	return (error);
1336}
1337
1338struct sigaction32 {
1339	u_int32_t	sa_u;
1340	int		sa_flags;
1341	sigset_t	sa_mask;
1342};
1343
1344int
1345ia32_sigaction(struct thread *td, struct ia32_sigaction_args *uap)
1346{
1347	struct sigaction32 s32;
1348	struct sigaction sa, osa, *sap;
1349	int error;
1350
1351	if (uap->act) {
1352		error = copyin(uap->act, &s32, sizeof(s32));
1353		if (error)
1354			return (error);
1355		sa.sa_handler = PTRIN(s32.sa_u);
1356		CP(s32, sa, sa_flags);
1357		CP(s32, sa, sa_mask);
1358		sap = &sa;
1359	} else
1360		sap = NULL;
1361	error = kern_sigaction(td, uap->sig, sap, &osa, 0);
1362	if (error != 0 && uap->oact != NULL) {
1363		s32.sa_u = PTROUT(osa.sa_handler);
1364		CP(osa, s32, sa_flags);
1365		CP(osa, s32, sa_mask);
1366		error = copyout(&s32, uap->oact, sizeof(s32));
1367	}
1368	return (error);
1369}
1370
1371#ifdef COMPAT_FREEBSD4
1372int
1373freebsd4_ia32_sigaction(struct thread *td, struct freebsd4_ia32_sigaction_args *uap)
1374{
1375	struct sigaction32 s32;
1376	struct sigaction sa, osa, *sap;
1377	int error;
1378
1379	if (uap->act) {
1380		error = copyin(uap->act, &s32, sizeof(s32));
1381		if (error)
1382			return (error);
1383		sa.sa_handler = PTRIN(s32.sa_u);
1384		CP(s32, sa, sa_flags);
1385		CP(s32, sa, sa_mask);
1386		sap = &sa;
1387	} else
1388		sap = NULL;
1389	error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
1390	if (error != 0 && uap->oact != NULL) {
1391		s32.sa_u = PTROUT(osa.sa_handler);
1392		CP(osa, s32, sa_flags);
1393		CP(osa, s32, sa_mask);
1394		error = copyout(&s32, uap->oact, sizeof(s32));
1395	}
1396	return (error);
1397}
1398#endif
1399
1400#if 0
1401
1402int
1403ia32_xxx(struct thread *td, struct ia32_xxx_args *uap)
1404{
1405	int error;
1406	caddr_t sg;
1407	struct yyy32 *p32, s32;
1408	struct yyy *p = NULL, s;
1409
1410	p32 = uap->zzz;
1411	if (p32) {
1412		sg = stackgap_init();
1413		p = stackgap_alloc(&sg, sizeof(struct yyy));
1414		uap->zzz = (struct yyy32 *)p;
1415		error = copyin(p32, &s32, sizeof(s32));
1416		if (error)
1417			return (error);
1418		/* translate in */
1419		error = copyout(&s, p, sizeof(s));
1420		if (error)
1421			return (error);
1422	}
1423	error = xxx(td, (struct xxx_args *) uap);
1424	if (error)
1425		return (error);
1426	if (p32) {
1427		error = copyin(p, &s, sizeof(s));
1428		if (error)
1429			return (error);
1430		/* translate out */
1431		error = copyout(&s32, p32, sizeof(s32));
1432	}
1433	return (error);
1434}
1435
1436#endif
1437