freebsd32_misc.c revision 104738
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 104738 2002-10-09 22:27:24Z 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/dkstat.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/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 <ia64/ia32/ia32_util.h>
78#include <ia64/ia32/ia32.h>
79#include <ia64/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 = SCARG(uap, rusage);
241	if (rusage32) {
242		sg = stackgap_init();
243		rusage = stackgap_alloc(&sg, sizeof(struct rusage));
244		SCARG(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 = SCARG(uap, buf);
308	maxcount = SCARG(uap, bufsize) / sizeof(struct statfs32);
309
310	if (sp32) {
311		sg = stackgap_init();
312		sp = stackgap_alloc(&sg, sizeof(struct statfs) * maxcount);
313		SCARG(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	int error;
363	caddr_t sg;
364	struct sigaltstack32 *p32, *op32, s32;
365	struct sigaltstack *p = NULL, *op = NULL, s;
366
367	p32 = SCARG(uap, ss);
368	if (p32) {
369		sg = stackgap_init();
370		p = stackgap_alloc(&sg, sizeof(struct sigaltstack));
371		SCARG(uap, ss) = (struct sigaltstack32 *)p;
372		error = copyin(p32, &s32, sizeof(s32));
373		if (error)
374			return (error);
375		PTRIN_CP(s32, s, ss_sp);
376		CP(s32, s, ss_size);
377		CP(s32, s, ss_flags);
378		error = copyout(&s, p, sizeof(s));
379		if (error)
380			return (error);
381	}
382	op32 = SCARG(uap, oss);
383	if (op32) {
384		sg = stackgap_init();
385		op = stackgap_alloc(&sg, sizeof(struct sigaltstack));
386		SCARG(uap, oss) = (struct sigaltstack32 *)op;
387	}
388	error = sigaltstack(td, (struct sigaltstack_args *) uap);
389	if (error)
390		return (error);
391	if (op32) {
392		error = copyin(op, &s, sizeof(s));
393		if (error)
394			return (error);
395		PTROUT_CP(s, s32, ss_sp);
396		CP(s, s32, ss_size);
397		CP(s, s32, ss_flags);
398		error = copyout(&s32, op32, sizeof(s32));
399	}
400	return (error);
401}
402
403int
404ia32_execve(struct thread *td, struct ia32_execve_args *uap)
405{
406	int error;
407	caddr_t sg;
408	struct execve_args ap;
409	u_int32_t *p32, arg;
410	char **p;
411	int count;
412
413	sg = stackgap_init();
414	CHECKALTEXIST(td, &sg, SCARG(uap, fname));
415	SCARG(&ap, fname) = SCARG(uap, fname);
416
417	if (SCARG(uap, argv)) {
418		count = 0;
419		p32 = SCARG(uap, argv);
420		do {
421			error = copyin(p32++, &arg, sizeof(arg));
422			if (error)
423				return error;
424			count++;
425		} while (arg != 0);
426		p = stackgap_alloc(&sg, count * sizeof(char *));
427		SCARG(&ap, argv) = p;
428		p32 = SCARG(uap, argv);
429		do {
430			error = copyin(p32++, &arg, sizeof(arg));
431			if (error)
432				return error;
433			*p++ = PTRIN(arg);
434		} while (arg != 0);
435	}
436	if (SCARG(uap, envv)) {
437		count = 0;
438		p32 = SCARG(uap, envv);
439		do {
440			error = copyin(p32++, &arg, sizeof(arg));
441			if (error)
442				return error;
443			count++;
444		} while (arg != 0);
445		p = stackgap_alloc(&sg, count * sizeof(char *));
446		SCARG(&ap, envv) = p;
447		p32 = SCARG(uap, envv);
448		do {
449			error = copyin(p32++, &arg, sizeof(arg));
450			if (error)
451				return error;
452			*p++ = PTRIN(arg);
453		} while (arg != 0);
454	}
455
456	return execve(td, &ap);
457}
458
459static int
460ia32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
461		  int prot, int fd, off_t pos)
462{
463	vm_map_t map;
464	vm_map_entry_t entry;
465	int rv;
466
467	map = &td->td_proc->p_vmspace->vm_map;
468	if (fd != -1)
469		prot |= VM_PROT_WRITE;
470
471	if (vm_map_lookup_entry(map, start, &entry)) {
472		if ((entry->protection & prot) != prot) {
473			rv = vm_map_protect(map,
474					    trunc_page(start),
475					    round_page(end),
476					    entry->protection | prot,
477					    FALSE);
478			if (rv != KERN_SUCCESS)
479				return (EINVAL);
480		}
481	} else {
482		vm_offset_t addr = trunc_page(start);
483		rv = vm_map_find(map, 0, 0,
484				 &addr, PAGE_SIZE, FALSE, prot,
485				 VM_PROT_ALL, 0);
486		if (rv != KERN_SUCCESS)
487			return (EINVAL);
488	}
489
490	if (fd != -1) {
491		struct pread_args r;
492		SCARG(&r, fd) = fd;
493		SCARG(&r, buf) = (void *) start;
494		SCARG(&r, nbyte) = end - start;
495		SCARG(&r, offset) = pos;
496		return (pread(td, &r));
497	} else {
498		while (start < end) {
499			subyte((void *) start, 0);
500			start++;
501		}
502		return (0);
503	}
504}
505
506int
507ia32_mmap(struct thread *td, struct ia32_mmap_args *uap)
508{
509	struct mmap_args ap;
510	vm_offset_t addr = (vm_offset_t) SCARG(uap, addr);
511	vm_size_t len	 = SCARG(uap, len);
512	int prot	 = SCARG(uap, prot);
513	int flags	 = SCARG(uap, flags);
514	int fd		 = SCARG(uap, fd);
515	off_t pos	 = (SCARG(uap, poslo)
516			    | ((off_t)SCARG(uap, poshi) << 32));
517	vm_size_t pageoff;
518	int error;
519
520	/*
521	 * Attempt to handle page size hassles.
522	 */
523	pageoff = (pos & PAGE_MASK);
524	if (flags & MAP_FIXED) {
525		vm_offset_t start, end;
526		start = addr;
527		end = addr + len;
528
529		if (start != trunc_page(start)) {
530			error = ia32_mmap_partial(td, start, round_page(start),
531						  prot, fd, pos);
532			if (fd != -1)
533				pos += round_page(start) - start;
534			start = round_page(start);
535		}
536		if (end != round_page(end)) {
537			vm_offset_t t = trunc_page(end);
538			error = ia32_mmap_partial(td, t, end,
539						  prot, fd,
540						  pos + t - start);
541			end = trunc_page(end);
542		}
543		if (end > start && fd != -1 && (pos & PAGE_MASK)) {
544			/*
545			 * We can't map this region at all. The specified
546			 * address doesn't have the same alignment as the file
547			 * position. Fake the mapping by simply reading the
548			 * entire region into memory. First we need to make
549			 * sure the region exists.
550			 */
551			vm_map_t map;
552			struct pread_args r;
553			int rv;
554
555			prot |= VM_PROT_WRITE;
556			map = &td->td_proc->p_vmspace->vm_map;
557			rv = vm_map_remove(map, start, end);
558			if (rv != KERN_SUCCESS)
559				return (EINVAL);
560			rv = vm_map_find(map, 0, 0,
561					 &start, end - start, FALSE,
562					 prot, VM_PROT_ALL, 0);
563			if (rv != KERN_SUCCESS)
564				return (EINVAL);
565			SCARG(&r, fd) = fd;
566			SCARG(&r, buf) = (void *) start;
567			SCARG(&r, nbyte) = end - start;
568			SCARG(&r, offset) = pos;
569			error = pread(td, &r);
570			if (error)
571				return (error);
572
573			td->td_retval[0] = addr;
574			return (0);
575		}
576		if (end == start) {
577			/*
578			 * After dealing with the ragged ends, there
579			 * might be none left.
580			 */
581			td->td_retval[0] = addr;
582			return (0);
583		}
584		addr = start;
585		len = end - start;
586	}
587
588	SCARG(&ap, addr) = (void *) addr;
589	SCARG(&ap, len) = len;
590	SCARG(&ap, prot) = prot;
591	SCARG(&ap, flags) = flags;
592	SCARG(&ap, fd) = fd;
593	SCARG(&ap, pos) = pos;
594
595	return (mmap(td, &ap));
596}
597
598struct itimerval32 {
599	struct timeval32 it_interval;
600	struct timeval32 it_value;
601};
602
603int
604ia32_setitimer(struct thread *td, struct ia32_setitimer_args *uap)
605{
606	int error;
607	caddr_t sg;
608	struct itimerval32 *p32, *op32, s32;
609	struct itimerval *p = NULL, *op = NULL, s;
610
611	p32 = SCARG(uap, itv);
612	if (p32) {
613		sg = stackgap_init();
614		p = stackgap_alloc(&sg, sizeof(struct itimerval));
615		SCARG(uap, itv) = (struct itimerval32 *)p;
616		error = copyin(p32, &s32, sizeof(s32));
617		if (error)
618			return (error);
619		TV_CP(s32, s, it_interval);
620		TV_CP(s32, s, it_value);
621		error = copyout(&s, p, sizeof(s));
622		if (error)
623			return (error);
624	}
625	op32 = SCARG(uap, oitv);
626	if (op32) {
627		sg = stackgap_init();
628		op = stackgap_alloc(&sg, sizeof(struct itimerval));
629		SCARG(uap, oitv) = (struct itimerval32 *)op;
630	}
631	error = setitimer(td, (struct setitimer_args *) uap);
632	if (error)
633		return (error);
634	if (op32) {
635		error = copyin(op, &s, sizeof(s));
636		if (error)
637			return (error);
638		TV_CP(s, s32, it_interval);
639		TV_CP(s, s32, it_value);
640		error = copyout(&s32, op32, sizeof(s32));
641	}
642	return (error);
643}
644
645int
646ia32_select(struct thread *td, struct ia32_select_args *uap)
647{
648	int error;
649	caddr_t sg;
650	struct timeval32 *p32, s32;
651	struct timeval *p = NULL, s;
652
653	p32 = SCARG(uap, tv);
654	if (p32) {
655		sg = stackgap_init();
656		p = stackgap_alloc(&sg, sizeof(struct timeval));
657		SCARG(uap, tv) = (struct timeval32 *)p;
658		error = copyin(p32, &s32, sizeof(s32));
659		if (error)
660			return (error);
661		CP(s32, s, tv_sec);
662		CP(s32, s, tv_usec);
663		error = copyout(&s, p, sizeof(s));
664		if (error)
665			return (error);
666	}
667	/*
668	 * XXX big-endian needs to convert the fd_sets too.
669	 */
670	return (select(td, (struct select_args *) uap));
671}
672
673int
674ia32_gettimeofday(struct thread *td, struct ia32_gettimeofday_args *uap)
675{
676	int error;
677	caddr_t sg;
678	struct timeval32 *p32, s32;
679	struct timeval *p = NULL, s;
680
681	p32 = SCARG(uap, tp);
682	if (p32) {
683		sg = stackgap_init();
684		p = stackgap_alloc(&sg, sizeof(struct timeval));
685		SCARG(uap, tp) = (struct timeval32 *)p;
686	}
687	error = gettimeofday(td, (struct gettimeofday_args *) uap);
688	if (error)
689		return (error);
690	if (p32) {
691		error = copyin(p, &s, sizeof(s));
692		if (error)
693			return (error);
694		CP(s, s32, tv_sec);
695		CP(s, s32, tv_usec);
696		error = copyout(&s32, p32, sizeof(s32));
697		if (error)
698			return (error);
699	}
700	return (error);
701}
702
703int
704ia32_getrusage(struct thread *td, struct ia32_getrusage_args *uap)
705{
706	int error;
707	caddr_t sg;
708	struct rusage32 *p32, s32;
709	struct rusage *p = NULL, s;
710
711	p32 = SCARG(uap, rusage);
712	if (p32) {
713		sg = stackgap_init();
714		p = stackgap_alloc(&sg, sizeof(struct rusage));
715		SCARG(uap, rusage) = (struct rusage32 *)p;
716	}
717	error = getrusage(td, (struct getrusage_args *) uap);
718	if (error)
719		return (error);
720	if (p32) {
721		error = copyin(p, &s, sizeof(s));
722		if (error)
723			return (error);
724		TV_CP(s, s32, ru_utime);
725		TV_CP(s, s32, ru_stime);
726		CP(s, s32, ru_maxrss);
727		CP(s, s32, ru_ixrss);
728		CP(s, s32, ru_idrss);
729		CP(s, s32, ru_isrss);
730		CP(s, s32, ru_minflt);
731		CP(s, s32, ru_majflt);
732		CP(s, s32, ru_nswap);
733		CP(s, s32, ru_inblock);
734		CP(s, s32, ru_oublock);
735		CP(s, s32, ru_msgsnd);
736		CP(s, s32, ru_msgrcv);
737		CP(s, s32, ru_nsignals);
738		CP(s, s32, ru_nvcsw);
739		CP(s, s32, ru_nivcsw);
740		error = copyout(&s32, p32, sizeof(s32));
741	}
742	return (error);
743}
744
745struct iovec32 {
746	u_int32_t iov_base;
747	int	iov_len;
748};
749#define	STACKGAPLEN	400
750
751int
752ia32_readv(struct thread *td, struct ia32_readv_args *uap)
753{
754	int error, osize, nsize, i;
755	caddr_t sg;
756	struct readv_args /* {
757		syscallarg(int) fd;
758		syscallarg(struct iovec *) iovp;
759		syscallarg(u_int) iovcnt;
760	} */ a;
761	struct iovec32 *oio;
762	struct iovec *nio;
763
764	sg = stackgap_init();
765
766	if (SCARG(uap, iovcnt) > (STACKGAPLEN / sizeof (struct iovec)))
767		return (EINVAL);
768
769	osize = SCARG(uap, iovcnt) * sizeof (struct iovec32);
770	nsize = SCARG(uap, iovcnt) * sizeof (struct iovec);
771
772	oio = malloc(osize, M_TEMP, M_WAITOK);
773	nio = malloc(nsize, M_TEMP, M_WAITOK);
774
775	error = 0;
776	if ((error = copyin(SCARG(uap, iovp), oio, osize)))
777		goto punt;
778	for (i = 0; i < SCARG(uap, iovcnt); i++) {
779		nio[i].iov_base = PTRIN(oio[i].iov_base);
780		nio[i].iov_len = oio[i].iov_len;
781	}
782
783	SCARG(&a, fd) = SCARG(uap, fd);
784	SCARG(&a, iovp) = stackgap_alloc(&sg, nsize);
785	SCARG(&a, iovcnt) = SCARG(uap, iovcnt);
786
787	if ((error = copyout(nio, (caddr_t)SCARG(&a, iovp), nsize)))
788		goto punt;
789	error = readv(td, &a);
790
791punt:
792	free(oio, M_TEMP);
793	free(nio, M_TEMP);
794	return (error);
795}
796
797int
798ia32_writev(struct thread *td, struct ia32_writev_args *uap)
799{
800	int error, i, nsize, osize;
801	caddr_t sg;
802	struct writev_args /* {
803		syscallarg(int) fd;
804		syscallarg(struct iovec *) iovp;
805		syscallarg(u_int) iovcnt;
806	} */ a;
807	struct iovec32 *oio;
808	struct iovec *nio;
809
810	sg = stackgap_init();
811
812	if (SCARG(uap, iovcnt) > (STACKGAPLEN / sizeof (struct iovec)))
813		return (EINVAL);
814
815	osize = SCARG(uap, iovcnt) * sizeof (struct iovec32);
816	nsize = SCARG(uap, iovcnt) * sizeof (struct iovec);
817
818	oio = malloc(osize, M_TEMP, M_WAITOK);
819	nio = malloc(nsize, M_TEMP, M_WAITOK);
820
821	error = 0;
822	if ((error = copyin(SCARG(uap, iovp), oio, osize)))
823		goto punt;
824	for (i = 0; i < SCARG(uap, iovcnt); i++) {
825		nio[i].iov_base = PTRIN(oio[i].iov_base);
826		nio[i].iov_len = oio[i].iov_len;
827	}
828
829	SCARG(&a, fd) = SCARG(uap, fd);
830	SCARG(&a, iovp) = stackgap_alloc(&sg, nsize);
831	SCARG(&a, iovcnt) = SCARG(uap, iovcnt);
832
833	if ((error = copyout(nio, (caddr_t)SCARG(&a, iovp), nsize)))
834		goto punt;
835	error = writev(td, &a);
836
837punt:
838	free(oio, M_TEMP);
839	free(nio, M_TEMP);
840	return (error);
841}
842
843int
844ia32_settimeofday(struct thread *td, struct ia32_settimeofday_args *uap)
845{
846	int error;
847	caddr_t sg;
848	struct timeval32 *p32, s32;
849	struct timeval *p = NULL, s;
850
851	p32 = SCARG(uap, tv);
852	if (p32) {
853		sg = stackgap_init();
854		p = stackgap_alloc(&sg, sizeof(struct timeval));
855		SCARG(uap, tv) = (struct timeval32 *)p;
856		error = copyin(p32, &s32, sizeof(s32));
857		if (error)
858			return (error);
859		CP(s32, s, tv_sec);
860		CP(s32, s, tv_usec);
861		error = copyout(&s, p, sizeof(s));
862		if (error)
863			return (error);
864	}
865	return (settimeofday(td, (struct settimeofday_args *) uap));
866}
867
868int
869ia32_utimes(struct thread *td, struct ia32_utimes_args *uap)
870{
871	int error;
872	caddr_t sg;
873	struct timeval32 *p32, s32[2];
874	struct timeval *p = NULL, s[2];
875
876	p32 = SCARG(uap, tptr);
877	if (p32) {
878		sg = stackgap_init();
879		p = stackgap_alloc(&sg, 2*sizeof(struct timeval));
880		SCARG(uap, tptr) = (struct timeval32 *)p;
881		error = copyin(p32, s32, sizeof(s32));
882		if (error)
883			return (error);
884		CP(s32[0], s[0], tv_sec);
885		CP(s32[0], s[0], tv_usec);
886		CP(s32[1], s[1], tv_sec);
887		CP(s32[1], s[1], tv_usec);
888		error = copyout(s, p, sizeof(s));
889		if (error)
890			return (error);
891	}
892	return (utimes(td, (struct utimes_args *) uap));
893}
894
895int
896ia32_adjtime(struct thread *td, struct ia32_adjtime_args *uap)
897{
898	int error;
899	caddr_t sg;
900	struct timeval32 *p32, *op32, s32;
901	struct timeval *p = NULL, *op = NULL, s;
902
903	p32 = SCARG(uap, delta);
904	if (p32) {
905		sg = stackgap_init();
906		p = stackgap_alloc(&sg, sizeof(struct timeval));
907		SCARG(uap, delta) = (struct timeval32 *)p;
908		error = copyin(p32, &s32, sizeof(s32));
909		if (error)
910			return (error);
911		CP(s32, s, tv_sec);
912		CP(s32, s, tv_usec);
913		error = copyout(&s, p, sizeof(s));
914		if (error)
915			return (error);
916	}
917	op32 = SCARG(uap, olddelta);
918	if (op32) {
919		sg = stackgap_init();
920		op = stackgap_alloc(&sg, sizeof(struct timeval));
921		SCARG(uap, olddelta) = (struct timeval32 *)op;
922	}
923	error = utimes(td, (struct utimes_args *) uap);
924	if (error)
925		return error;
926	if (op32) {
927		error = copyin(op, &s, sizeof(s));
928		if (error)
929			return (error);
930		CP(s, s32, tv_sec);
931		CP(s, s32, tv_usec);
932		error = copyout(&s32, op32, sizeof(s32));
933	}
934	return (error);
935}
936
937int
938ia32_statfs(struct thread *td, struct ia32_statfs_args *uap)
939{
940	int error;
941	caddr_t sg;
942	struct statfs32 *p32, s32;
943	struct statfs *p = NULL, s;
944
945	p32 = SCARG(uap, buf);
946	if (p32) {
947		sg = stackgap_init();
948		p = stackgap_alloc(&sg, sizeof(struct statfs));
949		SCARG(uap, buf) = (struct statfs32 *)p;
950	}
951	error = statfs(td, (struct statfs_args *) uap);
952	if (error)
953		return (error);
954	if (p32) {
955		error = copyin(p, &s, sizeof(s));
956		if (error)
957			return (error);
958		copy_statfs(&s, &s32);
959		error = copyout(&s32, p32, sizeof(s32));
960	}
961	return (error);
962}
963
964int
965ia32_fstatfs(struct thread *td, struct ia32_fstatfs_args *uap)
966{
967	int error;
968	caddr_t sg;
969	struct statfs32 *p32, s32;
970	struct statfs *p = NULL, s;
971
972	p32 = SCARG(uap, buf);
973	if (p32) {
974		sg = stackgap_init();
975		p = stackgap_alloc(&sg, sizeof(struct statfs));
976		SCARG(uap, buf) = (struct statfs32 *)p;
977	}
978	error = fstatfs(td, (struct fstatfs_args *) uap);
979	if (error)
980		return (error);
981	if (p32) {
982		error = copyin(p, &s, sizeof(s));
983		if (error)
984			return (error);
985		copy_statfs(&s, &s32);
986		error = copyout(&s32, p32, sizeof(s32));
987	}
988	return (error);
989}
990
991int
992ia32_semsys(struct thread *td, struct ia32_semsys_args *uap)
993{
994	/*
995	 * Vector through to semsys if it is loaded.
996	 */
997	return sysent[169].sy_call(td, uap);
998}
999
1000int
1001ia32_msgsys(struct thread *td, struct ia32_msgsys_args *uap)
1002{
1003	/*
1004	 * Vector through to msgsys if it is loaded.
1005	 */
1006	return sysent[170].sy_call(td, uap);
1007}
1008
1009int
1010ia32_shmsys(struct thread *td, struct ia32_shmsys_args *uap)
1011{
1012	/*
1013	 * Vector through to shmsys if it is loaded.
1014	 */
1015	return sysent[171].sy_call(td, uap);
1016}
1017
1018int
1019ia32_pread(struct thread *td, struct ia32_pread_args *uap)
1020{
1021	struct pread_args ap;
1022
1023	SCARG(&ap, fd) = SCARG(uap, fd);
1024	SCARG(&ap, buf) = SCARG(uap, buf);
1025	SCARG(&ap, nbyte) = SCARG(uap, nbyte);
1026	SCARG(&ap, offset) = (SCARG(uap, offsetlo)
1027			      | ((off_t)SCARG(uap, offsethi) << 32));
1028	return (pread(td, &ap));
1029}
1030
1031int
1032ia32_pwrite(struct thread *td, struct ia32_pwrite_args *uap)
1033{
1034	struct pwrite_args ap;
1035
1036	SCARG(&ap, fd) = SCARG(uap, fd);
1037	SCARG(&ap, buf) = SCARG(uap, buf);
1038	SCARG(&ap, nbyte) = SCARG(uap, nbyte);
1039	SCARG(&ap, offset) = (SCARG(uap, offsetlo)
1040			      | ((off_t)SCARG(uap, offsethi) << 32));
1041	return (pwrite(td, &ap));
1042}
1043
1044int
1045ia32_lseek(struct thread *td, struct ia32_lseek_args *uap)
1046{
1047	int error;
1048	struct lseek_args ap;
1049	off_t pos;
1050
1051	SCARG(&ap, fd) = SCARG(uap, fd);
1052	SCARG(&ap, offset) = (SCARG(uap, offsetlo)
1053			      | ((off_t)SCARG(uap, offsethi) << 32));
1054	SCARG(&ap, whence) = SCARG(uap, whence);
1055	error = lseek(td, &ap);
1056	/* Expand the quad return into two parts for eax and edx */
1057	pos = *(off_t *)(td->td_retval);
1058	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
1059	td->td_retval[1] = pos >> 32;		/* %edx */
1060	return error;
1061}
1062
1063int
1064ia32_truncate(struct thread *td, struct ia32_truncate_args *uap)
1065{
1066	struct truncate_args ap;
1067
1068	SCARG(&ap, path) = SCARG(uap, path);
1069	SCARG(&ap, length) = (SCARG(uap, lengthlo)
1070			      | ((off_t)SCARG(uap, lengthhi) << 32));
1071	return (truncate(td, &ap));
1072}
1073
1074int
1075ia32_ftruncate(struct thread *td, struct ia32_ftruncate_args *uap)
1076{
1077	struct ftruncate_args ap;
1078
1079	SCARG(&ap, fd) = SCARG(uap, fd);
1080	SCARG(&ap, length) = (SCARG(uap, lengthlo)
1081			      | ((off_t)SCARG(uap, lengthhi) << 32));
1082	return (ftruncate(td, &ap));
1083}
1084
1085#ifdef COMPAT_FREEBSD4
1086int
1087freebsd4_ia32_sendfile(struct thread *td,
1088    struct freebsd4_ia32_sendfile_args *uap)
1089{
1090	struct freebsd4_sendfile_args ap;
1091
1092	SCARG(&ap, fd) = SCARG(uap, fd);
1093	SCARG(&ap, s) = SCARG(uap, s);
1094	SCARG(&ap, offset) = (SCARG(uap, offsetlo)
1095			      | ((off_t)SCARG(uap, offsethi) << 32));
1096	SCARG(&ap, nbytes) = SCARG(uap, nbytes);	/* XXX check */
1097	SCARG(&ap, hdtr) = SCARG(uap, hdtr);		/* XXX check */
1098	SCARG(&ap, sbytes) = SCARG(uap, sbytes);	/* XXX FIXME!! */
1099	SCARG(&ap, flags) = SCARG(uap, flags);
1100	return (freebsd4_sendfile(td, &ap));
1101}
1102#endif
1103
1104int
1105ia32_sendfile(struct thread *td, struct ia32_sendfile_args *uap)
1106{
1107	struct sendfile_args ap;
1108
1109	SCARG(&ap, fd) = SCARG(uap, fd);
1110	SCARG(&ap, s) = SCARG(uap, s);
1111	SCARG(&ap, offset) = (SCARG(uap, offsetlo)
1112			      | ((off_t)SCARG(uap, offsethi) << 32));
1113	SCARG(&ap, nbytes) = SCARG(uap, nbytes);	/* XXX check */
1114	SCARG(&ap, hdtr) = SCARG(uap, hdtr);		/* XXX check */
1115	SCARG(&ap, sbytes) = SCARG(uap, sbytes);	/* XXX FIXME!! */
1116	SCARG(&ap, flags) = SCARG(uap, flags);
1117	return (sendfile(td, &ap));
1118}
1119
1120struct stat32 {
1121	udev_t	st_dev;
1122	ino_t	st_ino;
1123	mode_t	st_mode;
1124	nlink_t	st_nlink;
1125	uid_t	st_uid;
1126	gid_t	st_gid;
1127	udev_t	st_rdev;
1128	struct timespec32 st_atimespec;
1129	struct timespec32 st_mtimespec;
1130	struct timespec32 st_ctimespec;
1131	off_t	st_size;
1132	int64_t	st_blocks;
1133	u_int32_t st_blksize;
1134	u_int32_t st_flags;
1135	u_int32_t st_gen;
1136};
1137
1138static void
1139copy_stat( struct stat *in, struct stat32 *out)
1140{
1141	CP(*in, *out, st_dev);
1142	CP(*in, *out, st_ino);
1143	CP(*in, *out, st_mode);
1144	CP(*in, *out, st_nlink);
1145	CP(*in, *out, st_uid);
1146	CP(*in, *out, st_gid);
1147	CP(*in, *out, st_rdev);
1148	TS_CP(*in, *out, st_atimespec);
1149	TS_CP(*in, *out, st_mtimespec);
1150	TS_CP(*in, *out, st_ctimespec);
1151	CP(*in, *out, st_size);
1152	CP(*in, *out, st_blocks);
1153	CP(*in, *out, st_blksize);
1154	CP(*in, *out, st_flags);
1155	CP(*in, *out, st_gen);
1156}
1157
1158int
1159ia32_stat(struct thread *td, struct ia32_stat_args *uap)
1160{
1161	int error;
1162	caddr_t sg;
1163	struct stat32 *p32, s32;
1164	struct stat *p = NULL, s;
1165
1166	p32 = SCARG(uap, ub);
1167	if (p32) {
1168		sg = stackgap_init();
1169		p = stackgap_alloc(&sg, sizeof(struct stat));
1170		SCARG(uap, ub) = (struct stat32 *)p;
1171	}
1172	error = stat(td, (struct stat_args *) uap);
1173	if (error)
1174		return (error);
1175	if (p32) {
1176		error = copyin(p, &s, sizeof(s));
1177		if (error)
1178			return (error);
1179		copy_stat(&s, &s32);
1180		error = copyout(&s32, p32, sizeof(s32));
1181	}
1182	return (error);
1183}
1184
1185int
1186ia32_fstat(struct thread *td, struct ia32_fstat_args *uap)
1187{
1188	int error;
1189	caddr_t sg;
1190	struct stat32 *p32, s32;
1191	struct stat *p = NULL, s;
1192
1193	p32 = SCARG(uap, ub);
1194	if (p32) {
1195		sg = stackgap_init();
1196		p = stackgap_alloc(&sg, sizeof(struct stat));
1197		SCARG(uap, ub) = (struct stat32 *)p;
1198	}
1199	error = fstat(td, (struct fstat_args *) uap);
1200	if (error)
1201		return (error);
1202	if (p32) {
1203		error = copyin(p, &s, sizeof(s));
1204		if (error)
1205			return (error);
1206		copy_stat(&s, &s32);
1207		error = copyout(&s32, p32, sizeof(s32));
1208	}
1209	return (error);
1210}
1211
1212int
1213ia32_lstat(struct thread *td, struct ia32_lstat_args *uap)
1214{
1215	int error;
1216	caddr_t sg;
1217	struct stat32 *p32, s32;
1218	struct stat *p = NULL, s;
1219
1220	p32 = SCARG(uap, ub);
1221	if (p32) {
1222		sg = stackgap_init();
1223		p = stackgap_alloc(&sg, sizeof(struct stat));
1224		SCARG(uap, ub) = (struct stat32 *)p;
1225	}
1226	error = lstat(td, (struct lstat_args *) uap);
1227	if (error)
1228		return (error);
1229	if (p32) {
1230		error = copyin(p, &s, sizeof(s));
1231		if (error)
1232			return (error);
1233		copy_stat(&s, &s32);
1234		error = copyout(&s32, p32, sizeof(s32));
1235	}
1236	return (error);
1237}
1238
1239/*
1240 * MPSAFE
1241 */
1242int
1243ia32_sysctl(struct thread *td, struct ia32_sysctl_args *uap)
1244{
1245	int error, name[CTL_MAXNAME];
1246	size_t j, oldlen;
1247
1248	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1249		return (EINVAL);
1250
1251 	error = copyin(uap->name, &name, uap->namelen * sizeof(int));
1252 	if (error)
1253		return (error);
1254
1255	mtx_lock(&Giant);
1256
1257	if (uap->oldlenp)
1258		oldlen = fuword32(uap->oldlenp);
1259	else
1260		oldlen = 0;
1261	error = userland_sysctl(td, name, uap->namelen,
1262		uap->old, &oldlen, 1,
1263		uap->new, uap->newlen, &j);
1264	if (error && error != ENOMEM)
1265		goto done2;
1266	if (uap->oldlenp) {
1267		suword32(uap->oldlenp, j);
1268	}
1269done2:
1270	mtx_unlock(&Giant);
1271	return (error);
1272}
1273
1274struct sigaction32 {
1275	u_int32_t	sa_u;
1276	int		sa_flags;
1277	sigset_t	sa_mask;
1278};
1279
1280int
1281ia32_sigaction(struct thread *td, struct ia32_sigaction_args *uap)
1282{
1283	int error;
1284	caddr_t sg;
1285	struct sigaction32 *p32, *op32, s32;
1286	struct sigaction *p = NULL, *op = NULL, s;
1287
1288	p32 = SCARG(uap, act);
1289	if (p32) {
1290		sg = stackgap_init();
1291		p = stackgap_alloc(&sg, sizeof(struct sigaction));
1292		SCARG(uap, act) = (struct sigaction32 *)p;
1293		error = copyin(p32, &s32, sizeof(s32));
1294		if (error)
1295			return (error);
1296		s.sa_handler = PTRIN(s32.sa_u);
1297		CP(s32, s, sa_flags);
1298		CP(s32, s, sa_mask);
1299		error = copyout(&s, p, sizeof(s));
1300		if (error)
1301			return (error);
1302	}
1303	op32 = SCARG(uap, oact);
1304	if (op32) {
1305		sg = stackgap_init();
1306		op = stackgap_alloc(&sg, sizeof(struct sigaction));
1307		SCARG(uap, oact) = (struct sigaction32 *)op;
1308	}
1309	error = sigaction(td, (struct sigaction_args *) uap);
1310	if (error)
1311		return (error);
1312	if (op32) {
1313		error = copyin(op, &s, sizeof(s));
1314		if (error)
1315			return (error);
1316		s32.sa_u = PTROUT(s.sa_handler);
1317		CP(s, s32, sa_flags);
1318		CP(s, s32, sa_mask);
1319		error = copyout(&s32, op32, sizeof(s32));
1320	}
1321	return (error);
1322}
1323
1324#if 0
1325
1326int
1327ia32_xxx(struct thread *td, struct ia32_xxx_args *uap)
1328{
1329	int error;
1330	caddr_t sg;
1331	struct yyy32 *p32, s32;
1332	struct yyy *p = NULL, s;
1333
1334	p32 = SCARG(uap, zzz);
1335	if (p32) {
1336		sg = stackgap_init();
1337		p = stackgap_alloc(&sg, sizeof(struct yyy));
1338		SCARG(uap, zzz) = (struct yyy32 *)p;
1339		error = copyin(p32, &s32, sizeof(s32));
1340		if (error)
1341			return (error);
1342		/* translate in */
1343		error = copyout(&s, p, sizeof(s));
1344		if (error)
1345			return (error);
1346	}
1347	error = xxx(td, (struct xxx_args *) uap);
1348	if (error)
1349		return (error);
1350	if (p32) {
1351		error = copyin(p, &s, sizeof(s));
1352		if (error)
1353			return (error);
1354		/* translate out */
1355		error = copyout(&s32, p32, sizeof(s32));
1356	}
1357	return (error);
1358}
1359
1360#endif
1361