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