freebsd32_misc.c revision 111119
1100384Speter/*-
2100384Speter * Copyright (c) 2002 Doug Rabson
3100384Speter * All rights reserved.
4100384Speter *
5100384Speter * Redistribution and use in source and binary forms, with or without
6100384Speter * modification, are permitted provided that the following conditions
7100384Speter * are met:
8100384Speter * 1. Redistributions of source code must retain the above copyright
9100384Speter *    notice, this list of conditions and the following disclaimer.
10100384Speter * 2. Redistributions in binary form must reproduce the above copyright
11100384Speter *    notice, this list of conditions and the following disclaimer in the
12100384Speter *    documentation and/or other materials provided with the distribution.
13100384Speter *
14100384Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15100384Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16100384Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17100384Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18100384Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19100384Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20100384Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21100384Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22100384Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23100384Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24100384Speter * SUCH DAMAGE.
25100384Speter *
26100384Speter * $FreeBSD: head/sys/compat/freebsd32/freebsd32_misc.c 111119 2003-02-19 05:47:46Z imp $
27100384Speter */
28100384Speter
29104738Speter#include "opt_compat.h"
30104738Speter
31100384Speter#include <sys/param.h>
32100384Speter#include <sys/systm.h>
33100384Speter#include <sys/bus.h>
34100384Speter#include <sys/exec.h>
35100384Speter#include <sys/fcntl.h>
36100384Speter#include <sys/filedesc.h>
37100384Speter#include <sys/imgact.h>
38100384Speter#include <sys/kernel.h>
39100384Speter#include <sys/lock.h>
40100384Speter#include <sys/malloc.h>
41100384Speter#include <sys/file.h>		/* Must come after sys/malloc.h */
42100384Speter#include <sys/mman.h>
43100384Speter#include <sys/module.h>
44100384Speter#include <sys/mount.h>
45100384Speter#include <sys/mutex.h>
46100384Speter#include <sys/namei.h>
47100384Speter#include <sys/param.h>
48100384Speter#include <sys/proc.h>
49100384Speter#include <sys/reboot.h>
50100384Speter#include <sys/resource.h>
51100384Speter#include <sys/resourcevar.h>
52100384Speter#include <sys/selinfo.h>
53100384Speter#include <sys/pipe.h>		/* Must come after sys/selinfo.h */
54100384Speter#include <sys/signal.h>
55100384Speter#include <sys/signalvar.h>
56100384Speter#include <sys/socket.h>
57100384Speter#include <sys/socketvar.h>
58100384Speter#include <sys/stat.h>
59100384Speter#include <sys/sysctl.h>
60100384Speter#include <sys/sysent.h>
61100384Speter#include <sys/sysproto.h>
62100384Speter#include <sys/systm.h>
63100384Speter#include <sys/unistd.h>
64100384Speter#include <sys/user.h>
65100384Speter#include <sys/utsname.h>
66100384Speter#include <sys/vnode.h>
67100384Speter
68100384Speter#include <vm/vm.h>
69100384Speter#include <vm/vm_kern.h>
70100384Speter#include <vm/vm_param.h>
71100384Speter#include <vm/pmap.h>
72100384Speter#include <vm/vm_map.h>
73100384Speter#include <vm/vm_object.h>
74100384Speter#include <vm/vm_extern.h>
75100384Speter
76100384Speter#include <ia64/ia32/ia32_util.h>
77100384Speter#include <ia64/ia32/ia32.h>
78100384Speter#include <ia64/ia32/ia32_proto.h>
79100384Speter
80100384Speterstatic const char ia32_emul_path[] = "/compat/ia32";
81100384Speter/*
82100384Speter * [ taken from the linux emulator ]
83100384Speter * Search an alternate path before passing pathname arguments on
84100384Speter * to system calls. Useful for keeping a separate 'emulation tree'.
85100384Speter *
86100384Speter * If cflag is set, we check if an attempt can be made to create
87100384Speter * the named file, i.e. we check if the directory it should
88100384Speter * be in exists.
89100384Speter */
90100384Speterint
91100384Speteria32_emul_find(td, sgp, prefix, path, pbuf, cflag)
92100384Speter	struct thread	*td;
93100384Speter	caddr_t		*sgp;		/* Pointer to stackgap memory */
94100384Speter	const char	*prefix;
95100384Speter	char		*path;
96100384Speter	char		**pbuf;
97100384Speter	int		cflag;
98100384Speter{
99100384Speter	int			error;
100100384Speter	size_t			len, sz;
101100384Speter	char			*buf, *cp, *ptr;
102100384Speter	struct ucred		*ucred;
103100384Speter	struct nameidata	nd;
104100384Speter	struct nameidata	ndroot;
105100384Speter	struct vattr		vat;
106100384Speter	struct vattr		vatroot;
107100384Speter
108111119Simp	buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
109100384Speter	*pbuf = path;
110100384Speter
111100384Speter	for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++)
112100384Speter		continue;
113100384Speter
114100384Speter	sz = MAXPATHLEN - (ptr - buf);
115100384Speter
116100384Speter	/*
117100384Speter	 * If sgp is not given then the path is already in kernel space
118100384Speter	 */
119100384Speter	if (sgp == NULL)
120100384Speter		error = copystr(path, ptr, sz, &len);
121100384Speter	else
122100384Speter		error = copyinstr(path, ptr, sz, &len);
123100384Speter
124100384Speter	if (error) {
125100384Speter		free(buf, M_TEMP);
126100384Speter		return error;
127100384Speter	}
128100384Speter
129100384Speter	if (*ptr != '/') {
130100384Speter		free(buf, M_TEMP);
131100384Speter		return EINVAL;
132100384Speter	}
133100384Speter
134100384Speter	/*
135100384Speter	 *  We know that there is a / somewhere in this pathname.
136100384Speter	 *  Search backwards for it, to find the file's parent dir
137100384Speter	 *  to see if it exists in the alternate tree. If it does,
138100384Speter	 *  and we want to create a file (cflag is set). We don't
139100384Speter	 *  need to worry about the root comparison in this case.
140100384Speter	 */
141100384Speter
142100384Speter	if (cflag) {
143100384Speter		for (cp = &ptr[len] - 1; *cp != '/'; cp--)
144100384Speter			;
145100384Speter		*cp = '\0';
146100384Speter
147100384Speter		NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
148100384Speter
149100384Speter		if ((error = namei(&nd)) != 0) {
150100384Speter			free(buf, M_TEMP);
151100384Speter			return error;
152100384Speter		}
153100384Speter
154100384Speter		*cp = '/';
155100384Speter	} else {
156100384Speter		NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
157100384Speter
158100384Speter		if ((error = namei(&nd)) != 0) {
159100384Speter			free(buf, M_TEMP);
160100384Speter			return error;
161100384Speter		}
162100384Speter
163100384Speter		/*
164100384Speter		 * We now compare the vnode of the ia32_root to the one
165100384Speter		 * vnode asked. If they resolve to be the same, then we
166100384Speter		 * ignore the match so that the real root gets used.
167100384Speter		 * This avoids the problem of traversing "../.." to find the
168100384Speter		 * root directory and never finding it, because "/" resolves
169100384Speter		 * to the emulation root directory. This is expensive :-(
170100384Speter		 */
171100384Speter		NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, ia32_emul_path,
172100384Speter		    td);
173100384Speter
174100384Speter		if ((error = namei(&ndroot)) != 0) {
175100384Speter			/* Cannot happen! */
176100384Speter			free(buf, M_TEMP);
177100384Speter			vrele(nd.ni_vp);
178100384Speter			return error;
179100384Speter		}
180100384Speter
181100384Speter		ucred = td->td_ucred;
182100384Speter		if ((error = VOP_GETATTR(nd.ni_vp, &vat, ucred, td)) != 0) {
183100384Speter			goto bad;
184100384Speter		}
185100384Speter
186100384Speter		if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, ucred,
187100384Speter		    td)) != 0) {
188100384Speter			goto bad;
189100384Speter		}
190100384Speter
191100384Speter		if (vat.va_fsid == vatroot.va_fsid &&
192100384Speter		    vat.va_fileid == vatroot.va_fileid) {
193100384Speter			error = ENOENT;
194100384Speter			goto bad;
195100384Speter		}
196100384Speter
197100384Speter	}
198100384Speter	if (sgp == NULL)
199100384Speter		*pbuf = buf;
200100384Speter	else {
201100384Speter		sz = &ptr[len] - buf;
202100384Speter		*pbuf = stackgap_alloc(sgp, sz + 1);
203100384Speter		error = copyout(buf, *pbuf, sz);
204100384Speter		free(buf, M_TEMP);
205100384Speter	}
206100384Speter
207100384Speter	vrele(nd.ni_vp);
208100384Speter	if (!cflag)
209100384Speter		vrele(ndroot.ni_vp);
210100384Speter
211100384Speter	return error;
212100384Speter
213100384Speterbad:
214100384Speter	vrele(ndroot.ni_vp);
215100384Speter	vrele(nd.ni_vp);
216100384Speter	free(buf, M_TEMP);
217100384Speter	return error;
218100384Speter}
219100384Speter
220100384Speterint
221100384Speteria32_open(struct thread *td, struct ia32_open_args *uap)
222100384Speter{
223100384Speter	caddr_t sg;
224100384Speter
225100384Speter	sg = stackgap_init();
226100384Speter	CHECKALTEXIST(td, &sg, uap->path);
227100384Speter
228100384Speter	return open(td, (struct open_args *) uap);
229100384Speter}
230100384Speter
231100384Speterint
232100384Speteria32_wait4(struct thread *td, struct ia32_wait4_args *uap)
233100384Speter{
234100384Speter	int error;
235100384Speter	caddr_t sg;
236100384Speter	struct rusage32 *rusage32, ru32;
237100384Speter	struct rusage *rusage = NULL, ru;
238100384Speter
239107849Salfred	rusage32 = uap->rusage;
240100384Speter	if (rusage32) {
241100384Speter		sg = stackgap_init();
242100384Speter		rusage = stackgap_alloc(&sg, sizeof(struct rusage));
243107849Salfred		uap->rusage = (struct rusage32 *)rusage;
244100384Speter	}
245100384Speter	error = wait4(td, (struct wait_args *)uap);
246100384Speter	if (error)
247100384Speter		return (error);
248100384Speter	if (rusage32 && (error = copyin(rusage, &ru, sizeof(ru)) == 0)) {
249100384Speter		TV_CP(ru, ru32, ru_utime);
250100384Speter		TV_CP(ru, ru32, ru_stime);
251100384Speter		CP(ru, ru32, ru_maxrss);
252100384Speter		CP(ru, ru32, ru_ixrss);
253100384Speter		CP(ru, ru32, ru_idrss);
254100384Speter		CP(ru, ru32, ru_isrss);
255100384Speter		CP(ru, ru32, ru_minflt);
256100384Speter		CP(ru, ru32, ru_majflt);
257100384Speter		CP(ru, ru32, ru_nswap);
258100384Speter		CP(ru, ru32, ru_inblock);
259100384Speter		CP(ru, ru32, ru_oublock);
260100384Speter		CP(ru, ru32, ru_msgsnd);
261100384Speter		CP(ru, ru32, ru_msgrcv);
262100384Speter		CP(ru, ru32, ru_nsignals);
263100384Speter		CP(ru, ru32, ru_nvcsw);
264100384Speter		CP(ru, ru32, ru_nivcsw);
265100384Speter		error = copyout(&ru32, rusage32, sizeof(ru32));
266100384Speter	}
267100384Speter	return (error);
268100384Speter}
269100384Speter
270100384Speterstatic void
271100384Spetercopy_statfs(struct statfs *in, struct statfs32 *out)
272100384Speter{
273100384Speter	CP(*in, *out, f_bsize);
274100384Speter	CP(*in, *out, f_iosize);
275100384Speter	CP(*in, *out, f_blocks);
276100384Speter	CP(*in, *out, f_bfree);
277100384Speter	CP(*in, *out, f_bavail);
278100384Speter	CP(*in, *out, f_files);
279100384Speter	CP(*in, *out, f_ffree);
280100384Speter	CP(*in, *out, f_fsid);
281100384Speter	CP(*in, *out, f_owner);
282100384Speter	CP(*in, *out, f_type);
283100384Speter	CP(*in, *out, f_flags);
284100384Speter	CP(*in, *out, f_flags);
285100384Speter	CP(*in, *out, f_syncwrites);
286100384Speter	CP(*in, *out, f_asyncwrites);
287100384Speter	bcopy(in->f_fstypename,
288100384Speter	      out->f_fstypename, MFSNAMELEN);
289100384Speter	bcopy(in->f_mntonname,
290100384Speter	      out->f_mntonname, MNAMELEN);
291100384Speter	CP(*in, *out, f_syncreads);
292100384Speter	CP(*in, *out, f_asyncreads);
293100384Speter	bcopy(in->f_mntfromname,
294100384Speter	      out->f_mntfromname, MNAMELEN);
295100384Speter}
296100384Speter
297100384Speterint
298100384Speteria32_getfsstat(struct thread *td, struct ia32_getfsstat_args *uap)
299100384Speter{
300100384Speter	int error;
301100384Speter	caddr_t sg;
302100384Speter	struct statfs32 *sp32, stat32;
303100384Speter	struct statfs *sp = NULL, stat;
304100384Speter	int maxcount, count, i;
305100384Speter
306107849Salfred	sp32 = uap->buf;
307107849Salfred	maxcount = uap->bufsize / sizeof(struct statfs32);
308100384Speter
309100384Speter	if (sp32) {
310100384Speter		sg = stackgap_init();
311100384Speter		sp = stackgap_alloc(&sg, sizeof(struct statfs) * maxcount);
312107849Salfred		uap->buf = (struct statfs32 *)sp;
313100384Speter	}
314100384Speter	error = getfsstat(td, (struct getfsstat_args *) uap);
315100384Speter	if (sp32 && !error) {
316100384Speter		count = td->td_retval[0];
317100384Speter		for (i = 0; i < count; i++) {
318100384Speter			error = copyin(&sp[i], &stat, sizeof(stat));
319100384Speter			if (error)
320100384Speter				return (error);
321100384Speter			copy_statfs(&stat, &stat32);
322100384Speter			error = copyout(&stat32, &sp32[i], sizeof(stat32));
323100384Speter			if (error)
324100384Speter				return (error);
325100384Speter		}
326100384Speter	}
327100384Speter	return (error);
328100384Speter}
329100384Speter
330100384Speterint
331100384Speteria32_access(struct thread *td, struct ia32_access_args *uap)
332100384Speter{
333100384Speter	caddr_t sg;
334100384Speter
335100384Speter	sg = stackgap_init();
336100384Speter	CHECKALTEXIST(td, &sg, uap->path);
337100384Speter
338100384Speter	return access(td, (struct access_args *)uap);
339100384Speter}
340100384Speter
341100384Speterint
342100384Speteria32_chflags(struct thread *td, struct ia32_chflags_args *uap)
343100384Speter{
344100384Speter	caddr_t sg;
345100384Speter
346100384Speter	sg = stackgap_init();
347100384Speter	CHECKALTEXIST(td, &sg, uap->path);
348100384Speter
349100384Speter	return chflags(td, (struct chflags_args *)uap);
350100384Speter}
351100384Speter
352100384Speterstruct sigaltstack32 {
353100384Speter	u_int32_t	ss_sp;
354100384Speter	u_int32_t	ss_size;
355100384Speter	int		ss_flags;
356100384Speter};
357100384Speter
358100384Speterint
359100384Speteria32_sigaltstack(struct thread *td, struct ia32_sigaltstack_args *uap)
360100384Speter{
361100384Speter	int error;
362100384Speter	caddr_t sg;
363100384Speter	struct sigaltstack32 *p32, *op32, s32;
364100384Speter	struct sigaltstack *p = NULL, *op = NULL, s;
365100384Speter
366107849Salfred	p32 = uap->ss;
367100384Speter	if (p32) {
368100384Speter		sg = stackgap_init();
369100384Speter		p = stackgap_alloc(&sg, sizeof(struct sigaltstack));
370107849Salfred		uap->ss = (struct sigaltstack32 *)p;
371100384Speter		error = copyin(p32, &s32, sizeof(s32));
372100384Speter		if (error)
373100384Speter			return (error);
374100384Speter		PTRIN_CP(s32, s, ss_sp);
375100384Speter		CP(s32, s, ss_size);
376100384Speter		CP(s32, s, ss_flags);
377100384Speter		error = copyout(&s, p, sizeof(s));
378100384Speter		if (error)
379100384Speter			return (error);
380100384Speter	}
381107849Salfred	op32 = uap->oss;
382100384Speter	if (op32) {
383100384Speter		sg = stackgap_init();
384100384Speter		op = stackgap_alloc(&sg, sizeof(struct sigaltstack));
385107849Salfred		uap->oss = (struct sigaltstack32 *)op;
386100384Speter	}
387100384Speter	error = sigaltstack(td, (struct sigaltstack_args *) uap);
388100384Speter	if (error)
389100384Speter		return (error);
390100384Speter	if (op32) {
391100384Speter		error = copyin(op, &s, sizeof(s));
392100384Speter		if (error)
393100384Speter			return (error);
394100384Speter		PTROUT_CP(s, s32, ss_sp);
395100384Speter		CP(s, s32, ss_size);
396100384Speter		CP(s, s32, ss_flags);
397100384Speter		error = copyout(&s32, op32, sizeof(s32));
398100384Speter	}
399100384Speter	return (error);
400100384Speter}
401100384Speter
402100384Speterint
403100384Speteria32_execve(struct thread *td, struct ia32_execve_args *uap)
404100384Speter{
405100384Speter	int error;
406100384Speter	caddr_t sg;
407100384Speter	struct execve_args ap;
408100384Speter	u_int32_t *p32, arg;
409100384Speter	char **p;
410100384Speter	int count;
411100384Speter
412100384Speter	sg = stackgap_init();
413107849Salfred	CHECKALTEXIST(td, &sg, uap->fname);
414107849Salfred	ap.fname = uap->fname;
415100384Speter
416107849Salfred	if (uap->argv) {
417100384Speter		count = 0;
418107849Salfred		p32 = uap->argv;
419100384Speter		do {
420100384Speter			error = copyin(p32++, &arg, sizeof(arg));
421100384Speter			if (error)
422100384Speter				return error;
423100384Speter			count++;
424100384Speter		} while (arg != 0);
425100384Speter		p = stackgap_alloc(&sg, count * sizeof(char *));
426107849Salfred		ap.argv = p;
427107849Salfred		p32 = uap->argv;
428100384Speter		do {
429100384Speter			error = copyin(p32++, &arg, sizeof(arg));
430100384Speter			if (error)
431100384Speter				return error;
432100384Speter			*p++ = PTRIN(arg);
433100384Speter		} while (arg != 0);
434100384Speter	}
435107849Salfred	if (uap->envv) {
436100384Speter		count = 0;
437107849Salfred		p32 = uap->envv;
438100384Speter		do {
439100384Speter			error = copyin(p32++, &arg, sizeof(arg));
440100384Speter			if (error)
441100384Speter				return error;
442100384Speter			count++;
443100384Speter		} while (arg != 0);
444100384Speter		p = stackgap_alloc(&sg, count * sizeof(char *));
445107849Salfred		ap.envv = p;
446107849Salfred		p32 = uap->envv;
447100384Speter		do {
448100384Speter			error = copyin(p32++, &arg, sizeof(arg));
449100384Speter			if (error)
450100384Speter				return error;
451100384Speter			*p++ = PTRIN(arg);
452100384Speter		} while (arg != 0);
453100384Speter	}
454100384Speter
455100384Speter	return execve(td, &ap);
456100384Speter}
457100384Speter
458100384Speterstatic int
459100384Speteria32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
460100384Speter		  int prot, int fd, off_t pos)
461100384Speter{
462100384Speter	vm_map_t map;
463100384Speter	vm_map_entry_t entry;
464100384Speter	int rv;
465100384Speter
466100384Speter	map = &td->td_proc->p_vmspace->vm_map;
467100384Speter	if (fd != -1)
468100384Speter		prot |= VM_PROT_WRITE;
469100384Speter
470100384Speter	if (vm_map_lookup_entry(map, start, &entry)) {
471100384Speter		if ((entry->protection & prot) != prot) {
472100384Speter			rv = vm_map_protect(map,
473100384Speter					    trunc_page(start),
474100384Speter					    round_page(end),
475100384Speter					    entry->protection | prot,
476100384Speter					    FALSE);
477100384Speter			if (rv != KERN_SUCCESS)
478100384Speter				return (EINVAL);
479100384Speter		}
480100384Speter	} else {
481100384Speter		vm_offset_t addr = trunc_page(start);
482100384Speter		rv = vm_map_find(map, 0, 0,
483100384Speter				 &addr, PAGE_SIZE, FALSE, prot,
484100384Speter				 VM_PROT_ALL, 0);
485100384Speter		if (rv != KERN_SUCCESS)
486100384Speter			return (EINVAL);
487100384Speter	}
488100384Speter
489100384Speter	if (fd != -1) {
490100384Speter		struct pread_args r;
491107849Salfred		r.fd = fd;
492107849Salfred		r.buf = (void *) start;
493107849Salfred		r.nbyte = end - start;
494107849Salfred		r.offset = pos;
495100384Speter		return (pread(td, &r));
496100384Speter	} else {
497100384Speter		while (start < end) {
498100384Speter			subyte((void *) start, 0);
499100384Speter			start++;
500100384Speter		}
501100384Speter		return (0);
502100384Speter	}
503100384Speter}
504100384Speter
505100384Speterint
506100384Speteria32_mmap(struct thread *td, struct ia32_mmap_args *uap)
507100384Speter{
508100384Speter	struct mmap_args ap;
509107849Salfred	vm_offset_t addr = (vm_offset_t) uap->addr;
510107849Salfred	vm_size_t len	 = uap->len;
511107849Salfred	int prot	 = uap->prot;
512107849Salfred	int flags	 = uap->flags;
513107849Salfred	int fd		 = uap->fd;
514107849Salfred	off_t pos	 = (uap->poslo
515107849Salfred			    | ((off_t)uap->poshi << 32));
516100384Speter	vm_size_t pageoff;
517100384Speter	int error;
518100384Speter
519100384Speter	/*
520100384Speter	 * Attempt to handle page size hassles.
521100384Speter	 */
522100384Speter	pageoff = (pos & PAGE_MASK);
523100384Speter	if (flags & MAP_FIXED) {
524100384Speter		vm_offset_t start, end;
525100384Speter		start = addr;
526100384Speter		end = addr + len;
527100384Speter
528100384Speter		if (start != trunc_page(start)) {
529100384Speter			error = ia32_mmap_partial(td, start, round_page(start),
530100384Speter						  prot, fd, pos);
531100384Speter			if (fd != -1)
532100384Speter				pos += round_page(start) - start;
533100384Speter			start = round_page(start);
534100384Speter		}
535100384Speter		if (end != round_page(end)) {
536100384Speter			vm_offset_t t = trunc_page(end);
537100384Speter			error = ia32_mmap_partial(td, t, end,
538100384Speter						  prot, fd,
539100384Speter						  pos + t - start);
540100384Speter			end = trunc_page(end);
541100384Speter		}
542100384Speter		if (end > start && fd != -1 && (pos & PAGE_MASK)) {
543100384Speter			/*
544100384Speter			 * We can't map this region at all. The specified
545100384Speter			 * address doesn't have the same alignment as the file
546100384Speter			 * position. Fake the mapping by simply reading the
547100384Speter			 * entire region into memory. First we need to make
548100384Speter			 * sure the region exists.
549100384Speter			 */
550100384Speter			vm_map_t map;
551100384Speter			struct pread_args r;
552100384Speter			int rv;
553100384Speter
554100384Speter			prot |= VM_PROT_WRITE;
555100384Speter			map = &td->td_proc->p_vmspace->vm_map;
556100384Speter			rv = vm_map_remove(map, start, end);
557100384Speter			if (rv != KERN_SUCCESS)
558100384Speter				return (EINVAL);
559100384Speter			rv = vm_map_find(map, 0, 0,
560100384Speter					 &start, end - start, FALSE,
561100384Speter					 prot, VM_PROT_ALL, 0);
562100384Speter			if (rv != KERN_SUCCESS)
563100384Speter				return (EINVAL);
564107849Salfred			r.fd = fd;
565107849Salfred			r.buf = (void *) start;
566107849Salfred			r.nbyte = end - start;
567107849Salfred			r.offset = pos;
568100384Speter			error = pread(td, &r);
569100384Speter			if (error)
570100384Speter				return (error);
571100384Speter
572100384Speter			td->td_retval[0] = addr;
573100384Speter			return (0);
574100384Speter		}
575100384Speter		if (end == start) {
576100384Speter			/*
577100384Speter			 * After dealing with the ragged ends, there
578100384Speter			 * might be none left.
579100384Speter			 */
580100384Speter			td->td_retval[0] = addr;
581100384Speter			return (0);
582100384Speter		}
583100384Speter		addr = start;
584100384Speter		len = end - start;
585100384Speter	}
586100384Speter
587107849Salfred	ap.addr = (void *) addr;
588107849Salfred	ap.len = len;
589107849Salfred	ap.prot = prot;
590107849Salfred	ap.flags = flags;
591107849Salfred	ap.fd = fd;
592107849Salfred	ap.pos = pos;
593100384Speter
594100384Speter	return (mmap(td, &ap));
595100384Speter}
596100384Speter
597100384Speterstruct itimerval32 {
598100384Speter	struct timeval32 it_interval;
599100384Speter	struct timeval32 it_value;
600100384Speter};
601100384Speter
602100384Speterint
603100384Speteria32_setitimer(struct thread *td, struct ia32_setitimer_args *uap)
604100384Speter{
605100384Speter	int error;
606100384Speter	caddr_t sg;
607100384Speter	struct itimerval32 *p32, *op32, s32;
608100384Speter	struct itimerval *p = NULL, *op = NULL, s;
609100384Speter
610107849Salfred	p32 = uap->itv;
611100384Speter	if (p32) {
612100384Speter		sg = stackgap_init();
613100384Speter		p = stackgap_alloc(&sg, sizeof(struct itimerval));
614107849Salfred		uap->itv = (struct itimerval32 *)p;
615100384Speter		error = copyin(p32, &s32, sizeof(s32));
616100384Speter		if (error)
617100384Speter			return (error);
618100384Speter		TV_CP(s32, s, it_interval);
619100384Speter		TV_CP(s32, s, it_value);
620100384Speter		error = copyout(&s, p, sizeof(s));
621100384Speter		if (error)
622100384Speter			return (error);
623100384Speter	}
624107849Salfred	op32 = uap->oitv;
625100384Speter	if (op32) {
626100384Speter		sg = stackgap_init();
627100384Speter		op = stackgap_alloc(&sg, sizeof(struct itimerval));
628107849Salfred		uap->oitv = (struct itimerval32 *)op;
629100384Speter	}
630100384Speter	error = setitimer(td, (struct setitimer_args *) uap);
631100384Speter	if (error)
632100384Speter		return (error);
633100384Speter	if (op32) {
634100384Speter		error = copyin(op, &s, sizeof(s));
635100384Speter		if (error)
636100384Speter			return (error);
637100384Speter		TV_CP(s, s32, it_interval);
638100384Speter		TV_CP(s, s32, it_value);
639100384Speter		error = copyout(&s32, op32, sizeof(s32));
640100384Speter	}
641100384Speter	return (error);
642100384Speter}
643100384Speter
644100384Speterint
645100384Speteria32_select(struct thread *td, struct ia32_select_args *uap)
646100384Speter{
647100384Speter	int error;
648100384Speter	caddr_t sg;
649100384Speter	struct timeval32 *p32, s32;
650100384Speter	struct timeval *p = NULL, s;
651100384Speter
652107849Salfred	p32 = uap->tv;
653100384Speter	if (p32) {
654100384Speter		sg = stackgap_init();
655100384Speter		p = stackgap_alloc(&sg, sizeof(struct timeval));
656107849Salfred		uap->tv = (struct timeval32 *)p;
657100384Speter		error = copyin(p32, &s32, sizeof(s32));
658100384Speter		if (error)
659100384Speter			return (error);
660100384Speter		CP(s32, s, tv_sec);
661100384Speter		CP(s32, s, tv_usec);
662100384Speter		error = copyout(&s, p, sizeof(s));
663100384Speter		if (error)
664100384Speter			return (error);
665100384Speter	}
666100384Speter	/*
667100384Speter	 * XXX big-endian needs to convert the fd_sets too.
668100384Speter	 */
669100384Speter	return (select(td, (struct select_args *) uap));
670100384Speter}
671100384Speter
672100384Speterint
673100384Speteria32_gettimeofday(struct thread *td, struct ia32_gettimeofday_args *uap)
674100384Speter{
675100384Speter	int error;
676100384Speter	caddr_t sg;
677100384Speter	struct timeval32 *p32, s32;
678100384Speter	struct timeval *p = NULL, s;
679100384Speter
680107849Salfred	p32 = uap->tp;
681100384Speter	if (p32) {
682100384Speter		sg = stackgap_init();
683100384Speter		p = stackgap_alloc(&sg, sizeof(struct timeval));
684107849Salfred		uap->tp = (struct timeval32 *)p;
685100384Speter	}
686100384Speter	error = gettimeofday(td, (struct gettimeofday_args *) uap);
687100384Speter	if (error)
688100384Speter		return (error);
689100384Speter	if (p32) {
690100384Speter		error = copyin(p, &s, sizeof(s));
691100384Speter		if (error)
692100384Speter			return (error);
693100384Speter		CP(s, s32, tv_sec);
694100384Speter		CP(s, s32, tv_usec);
695100384Speter		error = copyout(&s32, p32, sizeof(s32));
696100384Speter		if (error)
697100384Speter			return (error);
698100384Speter	}
699100384Speter	return (error);
700100384Speter}
701100384Speter
702100384Speterint
703100384Speteria32_getrusage(struct thread *td, struct ia32_getrusage_args *uap)
704100384Speter{
705100384Speter	int error;
706100384Speter	caddr_t sg;
707100384Speter	struct rusage32 *p32, s32;
708100384Speter	struct rusage *p = NULL, s;
709100384Speter
710107849Salfred	p32 = uap->rusage;
711100384Speter	if (p32) {
712100384Speter		sg = stackgap_init();
713100384Speter		p = stackgap_alloc(&sg, sizeof(struct rusage));
714107849Salfred		uap->rusage = (struct rusage32 *)p;
715100384Speter	}
716100384Speter	error = getrusage(td, (struct getrusage_args *) uap);
717100384Speter	if (error)
718100384Speter		return (error);
719100384Speter	if (p32) {
720100384Speter		error = copyin(p, &s, sizeof(s));
721100384Speter		if (error)
722100384Speter			return (error);
723100384Speter		TV_CP(s, s32, ru_utime);
724100384Speter		TV_CP(s, s32, ru_stime);
725100384Speter		CP(s, s32, ru_maxrss);
726100384Speter		CP(s, s32, ru_ixrss);
727100384Speter		CP(s, s32, ru_idrss);
728100384Speter		CP(s, s32, ru_isrss);
729100384Speter		CP(s, s32, ru_minflt);
730100384Speter		CP(s, s32, ru_majflt);
731100384Speter		CP(s, s32, ru_nswap);
732100384Speter		CP(s, s32, ru_inblock);
733100384Speter		CP(s, s32, ru_oublock);
734100384Speter		CP(s, s32, ru_msgsnd);
735100384Speter		CP(s, s32, ru_msgrcv);
736100384Speter		CP(s, s32, ru_nsignals);
737100384Speter		CP(s, s32, ru_nvcsw);
738100384Speter		CP(s, s32, ru_nivcsw);
739100384Speter		error = copyout(&s32, p32, sizeof(s32));
740100384Speter	}
741100384Speter	return (error);
742100384Speter}
743100384Speter
744100384Speterstruct iovec32 {
745100384Speter	u_int32_t iov_base;
746100384Speter	int	iov_len;
747100384Speter};
748100384Speter#define	STACKGAPLEN	400
749100384Speter
750100384Speterint
751100384Speteria32_readv(struct thread *td, struct ia32_readv_args *uap)
752100384Speter{
753100384Speter	int error, osize, nsize, i;
754100384Speter	caddr_t sg;
755100384Speter	struct readv_args /* {
756100384Speter		syscallarg(int) fd;
757100384Speter		syscallarg(struct iovec *) iovp;
758100384Speter		syscallarg(u_int) iovcnt;
759100384Speter	} */ a;
760100384Speter	struct iovec32 *oio;
761100384Speter	struct iovec *nio;
762100384Speter
763100384Speter	sg = stackgap_init();
764100384Speter
765107849Salfred	if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
766100384Speter		return (EINVAL);
767100384Speter
768107849Salfred	osize = uap->iovcnt * sizeof (struct iovec32);
769107849Salfred	nsize = uap->iovcnt * sizeof (struct iovec);
770100384Speter
771111119Simp	oio = malloc(osize, M_TEMP, M_WAITOK);
772111119Simp	nio = malloc(nsize, M_TEMP, M_WAITOK);
773100384Speter
774100384Speter	error = 0;
775107849Salfred	if ((error = copyin(uap->iovp, oio, osize)))
776100384Speter		goto punt;
777107849Salfred	for (i = 0; i < uap->iovcnt; i++) {
778100384Speter		nio[i].iov_base = PTRIN(oio[i].iov_base);
779100384Speter		nio[i].iov_len = oio[i].iov_len;
780100384Speter	}
781100384Speter
782107849Salfred	a.fd = uap->fd;
783107849Salfred	a.iovp = stackgap_alloc(&sg, nsize);
784107849Salfred	a.iovcnt = uap->iovcnt;
785100384Speter
786107849Salfred	if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
787100384Speter		goto punt;
788100384Speter	error = readv(td, &a);
789100384Speter
790100384Speterpunt:
791100384Speter	free(oio, M_TEMP);
792100384Speter	free(nio, M_TEMP);
793100384Speter	return (error);
794100384Speter}
795100384Speter
796100384Speterint
797100384Speteria32_writev(struct thread *td, struct ia32_writev_args *uap)
798100384Speter{
799100384Speter	int error, i, nsize, osize;
800100384Speter	caddr_t sg;
801100384Speter	struct writev_args /* {
802100384Speter		syscallarg(int) fd;
803100384Speter		syscallarg(struct iovec *) iovp;
804100384Speter		syscallarg(u_int) iovcnt;
805100384Speter	} */ a;
806100384Speter	struct iovec32 *oio;
807100384Speter	struct iovec *nio;
808100384Speter
809100384Speter	sg = stackgap_init();
810100384Speter
811107849Salfred	if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
812100384Speter		return (EINVAL);
813100384Speter
814107849Salfred	osize = uap->iovcnt * sizeof (struct iovec32);
815107849Salfred	nsize = uap->iovcnt * sizeof (struct iovec);
816100384Speter
817111119Simp	oio = malloc(osize, M_TEMP, M_WAITOK);
818111119Simp	nio = malloc(nsize, M_TEMP, M_WAITOK);
819100384Speter
820100384Speter	error = 0;
821107849Salfred	if ((error = copyin(uap->iovp, oio, osize)))
822100384Speter		goto punt;
823107849Salfred	for (i = 0; i < uap->iovcnt; i++) {
824100384Speter		nio[i].iov_base = PTRIN(oio[i].iov_base);
825100384Speter		nio[i].iov_len = oio[i].iov_len;
826100384Speter	}
827100384Speter
828107849Salfred	a.fd = uap->fd;
829107849Salfred	a.iovp = stackgap_alloc(&sg, nsize);
830107849Salfred	a.iovcnt = uap->iovcnt;
831100384Speter
832107849Salfred	if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
833100384Speter		goto punt;
834100384Speter	error = writev(td, &a);
835100384Speter
836100384Speterpunt:
837100384Speter	free(oio, M_TEMP);
838100384Speter	free(nio, M_TEMP);
839100384Speter	return (error);
840100384Speter}
841100384Speter
842100384Speterint
843100384Speteria32_settimeofday(struct thread *td, struct ia32_settimeofday_args *uap)
844100384Speter{
845100384Speter	int error;
846100384Speter	caddr_t sg;
847100384Speter	struct timeval32 *p32, s32;
848100384Speter	struct timeval *p = NULL, s;
849100384Speter
850107849Salfred	p32 = uap->tv;
851100384Speter	if (p32) {
852100384Speter		sg = stackgap_init();
853100384Speter		p = stackgap_alloc(&sg, sizeof(struct timeval));
854107849Salfred		uap->tv = (struct timeval32 *)p;
855100384Speter		error = copyin(p32, &s32, sizeof(s32));
856100384Speter		if (error)
857100384Speter			return (error);
858100384Speter		CP(s32, s, tv_sec);
859100384Speter		CP(s32, s, tv_usec);
860100384Speter		error = copyout(&s, p, sizeof(s));
861100384Speter		if (error)
862100384Speter			return (error);
863100384Speter	}
864100384Speter	return (settimeofday(td, (struct settimeofday_args *) uap));
865100384Speter}
866100384Speter
867100384Speterint
868100384Speteria32_utimes(struct thread *td, struct ia32_utimes_args *uap)
869100384Speter{
870100384Speter	int error;
871100384Speter	caddr_t sg;
872100384Speter	struct timeval32 *p32, s32[2];
873100384Speter	struct timeval *p = NULL, s[2];
874100384Speter
875107849Salfred	p32 = uap->tptr;
876100384Speter	if (p32) {
877100384Speter		sg = stackgap_init();
878100384Speter		p = stackgap_alloc(&sg, 2*sizeof(struct timeval));
879107849Salfred		uap->tptr = (struct timeval32 *)p;
880100384Speter		error = copyin(p32, s32, sizeof(s32));
881100384Speter		if (error)
882100384Speter			return (error);
883100384Speter		CP(s32[0], s[0], tv_sec);
884100384Speter		CP(s32[0], s[0], tv_usec);
885100384Speter		CP(s32[1], s[1], tv_sec);
886100384Speter		CP(s32[1], s[1], tv_usec);
887100384Speter		error = copyout(s, p, sizeof(s));
888100384Speter		if (error)
889100384Speter			return (error);
890100384Speter	}
891100384Speter	return (utimes(td, (struct utimes_args *) uap));
892100384Speter}
893100384Speter
894100384Speterint
895100384Speteria32_adjtime(struct thread *td, struct ia32_adjtime_args *uap)
896100384Speter{
897100384Speter	int error;
898100384Speter	caddr_t sg;
899100384Speter	struct timeval32 *p32, *op32, s32;
900100384Speter	struct timeval *p = NULL, *op = NULL, s;
901100384Speter
902107849Salfred	p32 = uap->delta;
903100384Speter	if (p32) {
904100384Speter		sg = stackgap_init();
905100384Speter		p = stackgap_alloc(&sg, sizeof(struct timeval));
906107849Salfred		uap->delta = (struct timeval32 *)p;
907100384Speter		error = copyin(p32, &s32, sizeof(s32));
908100384Speter		if (error)
909100384Speter			return (error);
910100384Speter		CP(s32, s, tv_sec);
911100384Speter		CP(s32, s, tv_usec);
912100384Speter		error = copyout(&s, p, sizeof(s));
913100384Speter		if (error)
914100384Speter			return (error);
915100384Speter	}
916107849Salfred	op32 = uap->olddelta;
917100384Speter	if (op32) {
918100384Speter		sg = stackgap_init();
919100384Speter		op = stackgap_alloc(&sg, sizeof(struct timeval));
920107849Salfred		uap->olddelta = (struct timeval32 *)op;
921100384Speter	}
922100384Speter	error = utimes(td, (struct utimes_args *) uap);
923100384Speter	if (error)
924100384Speter		return error;
925100384Speter	if (op32) {
926100384Speter		error = copyin(op, &s, sizeof(s));
927100384Speter		if (error)
928100384Speter			return (error);
929100384Speter		CP(s, s32, tv_sec);
930100384Speter		CP(s, s32, tv_usec);
931100384Speter		error = copyout(&s32, op32, sizeof(s32));
932100384Speter	}
933100384Speter	return (error);
934100384Speter}
935100384Speter
936100384Speterint
937100384Speteria32_statfs(struct thread *td, struct ia32_statfs_args *uap)
938100384Speter{
939100384Speter	int error;
940100384Speter	caddr_t sg;
941100384Speter	struct statfs32 *p32, s32;
942100384Speter	struct statfs *p = NULL, s;
943100384Speter
944107849Salfred	p32 = uap->buf;
945100384Speter	if (p32) {
946100384Speter		sg = stackgap_init();
947100384Speter		p = stackgap_alloc(&sg, sizeof(struct statfs));
948107849Salfred		uap->buf = (struct statfs32 *)p;
949100384Speter	}
950100384Speter	error = statfs(td, (struct statfs_args *) uap);
951100384Speter	if (error)
952100384Speter		return (error);
953100384Speter	if (p32) {
954100384Speter		error = copyin(p, &s, sizeof(s));
955100384Speter		if (error)
956100384Speter			return (error);
957100384Speter		copy_statfs(&s, &s32);
958100384Speter		error = copyout(&s32, p32, sizeof(s32));
959100384Speter	}
960100384Speter	return (error);
961100384Speter}
962100384Speter
963100384Speterint
964100384Speteria32_fstatfs(struct thread *td, struct ia32_fstatfs_args *uap)
965100384Speter{
966100384Speter	int error;
967100384Speter	caddr_t sg;
968100384Speter	struct statfs32 *p32, s32;
969100384Speter	struct statfs *p = NULL, s;
970100384Speter
971107849Salfred	p32 = uap->buf;
972100384Speter	if (p32) {
973100384Speter		sg = stackgap_init();
974100384Speter		p = stackgap_alloc(&sg, sizeof(struct statfs));
975107849Salfred		uap->buf = (struct statfs32 *)p;
976100384Speter	}
977100384Speter	error = fstatfs(td, (struct fstatfs_args *) uap);
978100384Speter	if (error)
979100384Speter		return (error);
980100384Speter	if (p32) {
981100384Speter		error = copyin(p, &s, sizeof(s));
982100384Speter		if (error)
983100384Speter			return (error);
984100384Speter		copy_statfs(&s, &s32);
985100384Speter		error = copyout(&s32, p32, sizeof(s32));
986100384Speter	}
987100384Speter	return (error);
988100384Speter}
989100384Speter
990100384Speterint
991100384Speteria32_semsys(struct thread *td, struct ia32_semsys_args *uap)
992100384Speter{
993100384Speter	/*
994100384Speter	 * Vector through to semsys if it is loaded.
995100384Speter	 */
996100384Speter	return sysent[169].sy_call(td, uap);
997100384Speter}
998100384Speter
999100384Speterint
1000100384Speteria32_msgsys(struct thread *td, struct ia32_msgsys_args *uap)
1001100384Speter{
1002100384Speter	/*
1003100384Speter	 * Vector through to msgsys if it is loaded.
1004100384Speter	 */
1005100384Speter	return sysent[170].sy_call(td, uap);
1006100384Speter}
1007100384Speter
1008100384Speterint
1009100384Speteria32_shmsys(struct thread *td, struct ia32_shmsys_args *uap)
1010100384Speter{
1011100384Speter	/*
1012100384Speter	 * Vector through to shmsys if it is loaded.
1013100384Speter	 */
1014100384Speter	return sysent[171].sy_call(td, uap);
1015100384Speter}
1016100384Speter
1017100384Speterint
1018100384Speteria32_pread(struct thread *td, struct ia32_pread_args *uap)
1019100384Speter{
1020100384Speter	struct pread_args ap;
1021100384Speter
1022107849Salfred	ap.fd = uap->fd;
1023107849Salfred	ap.buf = uap->buf;
1024107849Salfred	ap.nbyte = uap->nbyte;
1025107849Salfred	ap.offset = (uap->offsetlo
1026107849Salfred			      | ((off_t)uap->offsethi << 32));
1027100384Speter	return (pread(td, &ap));
1028100384Speter}
1029100384Speter
1030100384Speterint
1031100384Speteria32_pwrite(struct thread *td, struct ia32_pwrite_args *uap)
1032100384Speter{
1033100384Speter	struct pwrite_args ap;
1034100384Speter
1035107849Salfred	ap.fd = uap->fd;
1036107849Salfred	ap.buf = uap->buf;
1037107849Salfred	ap.nbyte = uap->nbyte;
1038107849Salfred	ap.offset = (uap->offsetlo
1039107849Salfred			      | ((off_t)uap->offsethi << 32));
1040100384Speter	return (pwrite(td, &ap));
1041100384Speter}
1042100384Speter
1043100384Speterint
1044100384Speteria32_lseek(struct thread *td, struct ia32_lseek_args *uap)
1045100384Speter{
1046100384Speter	int error;
1047100384Speter	struct lseek_args ap;
1048100384Speter	off_t pos;
1049100384Speter
1050107849Salfred	ap.fd = uap->fd;
1051107849Salfred	ap.offset = (uap->offsetlo
1052107849Salfred			      | ((off_t)uap->offsethi << 32));
1053107849Salfred	ap.whence = uap->whence;
1054100384Speter	error = lseek(td, &ap);
1055100384Speter	/* Expand the quad return into two parts for eax and edx */
1056100384Speter	pos = *(off_t *)(td->td_retval);
1057100384Speter	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
1058100384Speter	td->td_retval[1] = pos >> 32;		/* %edx */
1059100384Speter	return error;
1060100384Speter}
1061100384Speter
1062100384Speterint
1063100384Speteria32_truncate(struct thread *td, struct ia32_truncate_args *uap)
1064100384Speter{
1065100384Speter	struct truncate_args ap;
1066100384Speter
1067107849Salfred	ap.path = uap->path;
1068107849Salfred	ap.length = (uap->lengthlo
1069107849Salfred			      | ((off_t)uap->lengthhi << 32));
1070100384Speter	return (truncate(td, &ap));
1071100384Speter}
1072100384Speter
1073100384Speterint
1074100384Speteria32_ftruncate(struct thread *td, struct ia32_ftruncate_args *uap)
1075100384Speter{
1076100384Speter	struct ftruncate_args ap;
1077100384Speter
1078107849Salfred	ap.fd = uap->fd;
1079107849Salfred	ap.length = (uap->lengthlo
1080107849Salfred			      | ((off_t)uap->lengthhi << 32));
1081100384Speter	return (ftruncate(td, &ap));
1082100384Speter}
1083100384Speter
1084104738Speter#ifdef COMPAT_FREEBSD4
1085100384Speterint
1086104738Speterfreebsd4_ia32_sendfile(struct thread *td,
1087104738Speter    struct freebsd4_ia32_sendfile_args *uap)
1088104738Speter{
1089104738Speter	struct freebsd4_sendfile_args ap;
1090104738Speter
1091107849Salfred	ap.fd = uap->fd;
1092107849Salfred	ap.s = uap->s;
1093107849Salfred	ap.offset = (uap->offsetlo
1094107849Salfred			      | ((off_t)uap->offsethi << 32));
1095107849Salfred	ap.nbytes = uap->nbytes;	/* XXX check */
1096107849Salfred	ap.hdtr = uap->hdtr;		/* XXX check */
1097107849Salfred	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1098107849Salfred	ap.flags = uap->flags;
1099104738Speter	return (freebsd4_sendfile(td, &ap));
1100104738Speter}
1101104738Speter#endif
1102104738Speter
1103104738Speterint
1104100384Speteria32_sendfile(struct thread *td, struct ia32_sendfile_args *uap)
1105100384Speter{
1106100384Speter	struct sendfile_args ap;
1107100384Speter
1108107849Salfred	ap.fd = uap->fd;
1109107849Salfred	ap.s = uap->s;
1110107849Salfred	ap.offset = (uap->offsetlo
1111107849Salfred			      | ((off_t)uap->offsethi << 32));
1112107849Salfred	ap.nbytes = uap->nbytes;	/* XXX check */
1113107849Salfred	ap.hdtr = uap->hdtr;		/* XXX check */
1114107849Salfred	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1115107849Salfred	ap.flags = uap->flags;
1116100384Speter	return (sendfile(td, &ap));
1117100384Speter}
1118100384Speter
1119100384Speterstruct stat32 {
1120100384Speter	udev_t	st_dev;
1121100384Speter	ino_t	st_ino;
1122100384Speter	mode_t	st_mode;
1123100384Speter	nlink_t	st_nlink;
1124100384Speter	uid_t	st_uid;
1125100384Speter	gid_t	st_gid;
1126100384Speter	udev_t	st_rdev;
1127100384Speter	struct timespec32 st_atimespec;
1128100384Speter	struct timespec32 st_mtimespec;
1129100384Speter	struct timespec32 st_ctimespec;
1130100384Speter	off_t	st_size;
1131100384Speter	int64_t	st_blocks;
1132100384Speter	u_int32_t st_blksize;
1133100384Speter	u_int32_t st_flags;
1134100384Speter	u_int32_t st_gen;
1135100384Speter};
1136100384Speter
1137100384Speterstatic void
1138100384Spetercopy_stat( struct stat *in, struct stat32 *out)
1139100384Speter{
1140100384Speter	CP(*in, *out, st_dev);
1141100384Speter	CP(*in, *out, st_ino);
1142100384Speter	CP(*in, *out, st_mode);
1143100384Speter	CP(*in, *out, st_nlink);
1144100384Speter	CP(*in, *out, st_uid);
1145100384Speter	CP(*in, *out, st_gid);
1146100384Speter	CP(*in, *out, st_rdev);
1147100384Speter	TS_CP(*in, *out, st_atimespec);
1148100384Speter	TS_CP(*in, *out, st_mtimespec);
1149100384Speter	TS_CP(*in, *out, st_ctimespec);
1150100384Speter	CP(*in, *out, st_size);
1151100384Speter	CP(*in, *out, st_blocks);
1152100384Speter	CP(*in, *out, st_blksize);
1153100384Speter	CP(*in, *out, st_flags);
1154100384Speter	CP(*in, *out, st_gen);
1155100384Speter}
1156100384Speter
1157100384Speterint
1158100384Speteria32_stat(struct thread *td, struct ia32_stat_args *uap)
1159100384Speter{
1160100384Speter	int error;
1161100384Speter	caddr_t sg;
1162100384Speter	struct stat32 *p32, s32;
1163100384Speter	struct stat *p = NULL, s;
1164100384Speter
1165107849Salfred	p32 = uap->ub;
1166100384Speter	if (p32) {
1167100384Speter		sg = stackgap_init();
1168100384Speter		p = stackgap_alloc(&sg, sizeof(struct stat));
1169107849Salfred		uap->ub = (struct stat32 *)p;
1170100384Speter	}
1171100384Speter	error = stat(td, (struct stat_args *) uap);
1172100384Speter	if (error)
1173100384Speter		return (error);
1174100384Speter	if (p32) {
1175100384Speter		error = copyin(p, &s, sizeof(s));
1176100384Speter		if (error)
1177100384Speter			return (error);
1178100384Speter		copy_stat(&s, &s32);
1179100384Speter		error = copyout(&s32, p32, sizeof(s32));
1180100384Speter	}
1181100384Speter	return (error);
1182100384Speter}
1183100384Speter
1184100384Speterint
1185100384Speteria32_fstat(struct thread *td, struct ia32_fstat_args *uap)
1186100384Speter{
1187100384Speter	int error;
1188100384Speter	caddr_t sg;
1189100384Speter	struct stat32 *p32, s32;
1190100384Speter	struct stat *p = NULL, s;
1191100384Speter
1192107849Salfred	p32 = uap->ub;
1193100384Speter	if (p32) {
1194100384Speter		sg = stackgap_init();
1195100384Speter		p = stackgap_alloc(&sg, sizeof(struct stat));
1196107849Salfred		uap->ub = (struct stat32 *)p;
1197100384Speter	}
1198100384Speter	error = fstat(td, (struct fstat_args *) uap);
1199100384Speter	if (error)
1200100384Speter		return (error);
1201100384Speter	if (p32) {
1202100384Speter		error = copyin(p, &s, sizeof(s));
1203100384Speter		if (error)
1204100384Speter			return (error);
1205100384Speter		copy_stat(&s, &s32);
1206100384Speter		error = copyout(&s32, p32, sizeof(s32));
1207100384Speter	}
1208100384Speter	return (error);
1209100384Speter}
1210100384Speter
1211100384Speterint
1212100384Speteria32_lstat(struct thread *td, struct ia32_lstat_args *uap)
1213100384Speter{
1214100384Speter	int error;
1215100384Speter	caddr_t sg;
1216100384Speter	struct stat32 *p32, s32;
1217100384Speter	struct stat *p = NULL, s;
1218100384Speter
1219107849Salfred	p32 = uap->ub;
1220100384Speter	if (p32) {
1221100384Speter		sg = stackgap_init();
1222100384Speter		p = stackgap_alloc(&sg, sizeof(struct stat));
1223107849Salfred		uap->ub = (struct stat32 *)p;
1224100384Speter	}
1225100384Speter	error = lstat(td, (struct lstat_args *) uap);
1226100384Speter	if (error)
1227100384Speter		return (error);
1228100384Speter	if (p32) {
1229100384Speter		error = copyin(p, &s, sizeof(s));
1230100384Speter		if (error)
1231100384Speter			return (error);
1232100384Speter		copy_stat(&s, &s32);
1233100384Speter		error = copyout(&s32, p32, sizeof(s32));
1234100384Speter	}
1235100384Speter	return (error);
1236100384Speter}
1237100384Speter
1238100384Speter/*
1239100384Speter * MPSAFE
1240100384Speter */
1241100384Speterint
1242100384Speteria32_sysctl(struct thread *td, struct ia32_sysctl_args *uap)
1243100384Speter{
1244100384Speter	int error, name[CTL_MAXNAME];
1245100384Speter	size_t j, oldlen;
1246100384Speter
1247100384Speter	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1248100384Speter		return (EINVAL);
1249100384Speter
1250100384Speter 	error = copyin(uap->name, &name, uap->namelen * sizeof(int));
1251100384Speter 	if (error)
1252100384Speter		return (error);
1253100384Speter
1254100384Speter	mtx_lock(&Giant);
1255100384Speter
1256100384Speter	if (uap->oldlenp)
1257100384Speter		oldlen = fuword32(uap->oldlenp);
1258100384Speter	else
1259100384Speter		oldlen = 0;
1260100384Speter	error = userland_sysctl(td, name, uap->namelen,
1261100384Speter		uap->old, &oldlen, 1,
1262100384Speter		uap->new, uap->newlen, &j);
1263100384Speter	if (error && error != ENOMEM)
1264100384Speter		goto done2;
1265100384Speter	if (uap->oldlenp) {
1266100384Speter		suword32(uap->oldlenp, j);
1267100384Speter	}
1268100384Speterdone2:
1269100384Speter	mtx_unlock(&Giant);
1270100384Speter	return (error);
1271100384Speter}
1272100384Speter
1273100384Speterstruct sigaction32 {
1274100384Speter	u_int32_t	sa_u;
1275100384Speter	int		sa_flags;
1276100384Speter	sigset_t	sa_mask;
1277100384Speter};
1278100384Speter
1279100384Speterint
1280100384Speteria32_sigaction(struct thread *td, struct ia32_sigaction_args *uap)
1281100384Speter{
1282100384Speter	int error;
1283100384Speter	caddr_t sg;
1284100384Speter	struct sigaction32 *p32, *op32, s32;
1285100384Speter	struct sigaction *p = NULL, *op = NULL, s;
1286100384Speter
1287107849Salfred	p32 = uap->act;
1288100384Speter	if (p32) {
1289100384Speter		sg = stackgap_init();
1290100384Speter		p = stackgap_alloc(&sg, sizeof(struct sigaction));
1291107849Salfred		uap->act = (struct sigaction32 *)p;
1292100384Speter		error = copyin(p32, &s32, sizeof(s32));
1293100384Speter		if (error)
1294100384Speter			return (error);
1295100384Speter		s.sa_handler = PTRIN(s32.sa_u);
1296100384Speter		CP(s32, s, sa_flags);
1297100384Speter		CP(s32, s, sa_mask);
1298100384Speter		error = copyout(&s, p, sizeof(s));
1299100384Speter		if (error)
1300100384Speter			return (error);
1301100384Speter	}
1302107849Salfred	op32 = uap->oact;
1303100384Speter	if (op32) {
1304100384Speter		sg = stackgap_init();
1305100384Speter		op = stackgap_alloc(&sg, sizeof(struct sigaction));
1306107849Salfred		uap->oact = (struct sigaction32 *)op;
1307100384Speter	}
1308100384Speter	error = sigaction(td, (struct sigaction_args *) uap);
1309100384Speter	if (error)
1310100384Speter		return (error);
1311100384Speter	if (op32) {
1312100384Speter		error = copyin(op, &s, sizeof(s));
1313100384Speter		if (error)
1314100384Speter			return (error);
1315100384Speter		s32.sa_u = PTROUT(s.sa_handler);
1316100384Speter		CP(s, s32, sa_flags);
1317100384Speter		CP(s, s32, sa_mask);
1318100384Speter		error = copyout(&s32, op32, sizeof(s32));
1319100384Speter	}
1320100384Speter	return (error);
1321100384Speter}
1322100384Speter
1323100384Speter#if 0
1324100384Speter
1325100384Speterint
1326100384Speteria32_xxx(struct thread *td, struct ia32_xxx_args *uap)
1327100384Speter{
1328100384Speter	int error;
1329100384Speter	caddr_t sg;
1330100384Speter	struct yyy32 *p32, s32;
1331100384Speter	struct yyy *p = NULL, s;
1332100384Speter
1333107849Salfred	p32 = uap->zzz;
1334100384Speter	if (p32) {
1335100384Speter		sg = stackgap_init();
1336100384Speter		p = stackgap_alloc(&sg, sizeof(struct yyy));
1337107849Salfred		uap->zzz = (struct yyy32 *)p;
1338100384Speter		error = copyin(p32, &s32, sizeof(s32));
1339100384Speter		if (error)
1340100384Speter			return (error);
1341100384Speter		/* translate in */
1342100384Speter		error = copyout(&s, p, sizeof(s));
1343100384Speter		if (error)
1344100384Speter			return (error);
1345100384Speter	}
1346100384Speter	error = xxx(td, (struct xxx_args *) uap);
1347100384Speter	if (error)
1348100384Speter		return (error);
1349100384Speter	if (p32) {
1350100384Speter		error = copyin(p, &s, sizeof(s));
1351100384Speter		if (error)
1352100384Speter			return (error);
1353100384Speter		/* translate out */
1354100384Speter		error = copyout(&s32, p32, sizeof(s32));
1355100384Speter	}
1356100384Speter	return (error);
1357100384Speter}
1358100384Speter
1359100384Speter#endif
1360