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