freebsd32_misc.c revision 114987
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 114987 2003-05-14 04:10:49Z peter $
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>
59113859Sjhb#include <sys/syscallsubr.h>
60100384Speter#include <sys/sysctl.h>
61100384Speter#include <sys/sysent.h>
62100384Speter#include <sys/sysproto.h>
63100384Speter#include <sys/systm.h>
64100384Speter#include <sys/unistd.h>
65100384Speter#include <sys/user.h>
66100384Speter#include <sys/utsname.h>
67100384Speter#include <sys/vnode.h>
68100384Speter
69100384Speter#include <vm/vm.h>
70100384Speter#include <vm/vm_kern.h>
71100384Speter#include <vm/vm_param.h>
72100384Speter#include <vm/pmap.h>
73100384Speter#include <vm/vm_map.h>
74100384Speter#include <vm/vm_object.h>
75100384Speter#include <vm/vm_extern.h>
76100384Speter
77114987Speter#include <amd64/ia32/ia32_util.h>
78114987Speter#include <amd64/ia32/ia32.h>
79114987Speter#include <amd64/ia32/ia32_proto.h>
80100384Speter
81100384Speterstatic const char ia32_emul_path[] = "/compat/ia32";
82100384Speter/*
83100384Speter * [ taken from the linux emulator ]
84100384Speter * Search an alternate path before passing pathname arguments on
85100384Speter * to system calls. Useful for keeping a separate 'emulation tree'.
86100384Speter *
87100384Speter * If cflag is set, we check if an attempt can be made to create
88100384Speter * the named file, i.e. we check if the directory it should
89100384Speter * be in exists.
90100384Speter */
91100384Speterint
92100384Speteria32_emul_find(td, sgp, prefix, path, pbuf, cflag)
93100384Speter	struct thread	*td;
94100384Speter	caddr_t		*sgp;		/* Pointer to stackgap memory */
95100384Speter	const char	*prefix;
96100384Speter	char		*path;
97100384Speter	char		**pbuf;
98100384Speter	int		cflag;
99100384Speter{
100100384Speter	int			error;
101100384Speter	size_t			len, sz;
102100384Speter	char			*buf, *cp, *ptr;
103100384Speter	struct ucred		*ucred;
104100384Speter	struct nameidata	nd;
105100384Speter	struct nameidata	ndroot;
106100384Speter	struct vattr		vat;
107100384Speter	struct vattr		vatroot;
108100384Speter
109111119Simp	buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
110100384Speter	*pbuf = path;
111100384Speter
112100384Speter	for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++)
113100384Speter		continue;
114100384Speter
115100384Speter	sz = MAXPATHLEN - (ptr - buf);
116100384Speter
117100384Speter	/*
118100384Speter	 * If sgp is not given then the path is already in kernel space
119100384Speter	 */
120100384Speter	if (sgp == NULL)
121100384Speter		error = copystr(path, ptr, sz, &len);
122100384Speter	else
123100384Speter		error = copyinstr(path, ptr, sz, &len);
124100384Speter
125100384Speter	if (error) {
126100384Speter		free(buf, M_TEMP);
127100384Speter		return error;
128100384Speter	}
129100384Speter
130100384Speter	if (*ptr != '/') {
131100384Speter		free(buf, M_TEMP);
132100384Speter		return EINVAL;
133100384Speter	}
134100384Speter
135100384Speter	/*
136100384Speter	 *  We know that there is a / somewhere in this pathname.
137100384Speter	 *  Search backwards for it, to find the file's parent dir
138100384Speter	 *  to see if it exists in the alternate tree. If it does,
139100384Speter	 *  and we want to create a file (cflag is set). We don't
140100384Speter	 *  need to worry about the root comparison in this case.
141100384Speter	 */
142100384Speter
143100384Speter	if (cflag) {
144100384Speter		for (cp = &ptr[len] - 1; *cp != '/'; cp--)
145100384Speter			;
146100384Speter		*cp = '\0';
147100384Speter
148100384Speter		NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
149100384Speter
150100384Speter		if ((error = namei(&nd)) != 0) {
151100384Speter			free(buf, M_TEMP);
152100384Speter			return error;
153100384Speter		}
154100384Speter
155100384Speter		*cp = '/';
156100384Speter	} else {
157100384Speter		NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
158100384Speter
159100384Speter		if ((error = namei(&nd)) != 0) {
160100384Speter			free(buf, M_TEMP);
161100384Speter			return error;
162100384Speter		}
163100384Speter
164100384Speter		/*
165100384Speter		 * We now compare the vnode of the ia32_root to the one
166100384Speter		 * vnode asked. If they resolve to be the same, then we
167100384Speter		 * ignore the match so that the real root gets used.
168100384Speter		 * This avoids the problem of traversing "../.." to find the
169100384Speter		 * root directory and never finding it, because "/" resolves
170100384Speter		 * to the emulation root directory. This is expensive :-(
171100384Speter		 */
172100384Speter		NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, ia32_emul_path,
173100384Speter		    td);
174100384Speter
175100384Speter		if ((error = namei(&ndroot)) != 0) {
176100384Speter			/* Cannot happen! */
177100384Speter			free(buf, M_TEMP);
178100384Speter			vrele(nd.ni_vp);
179100384Speter			return error;
180100384Speter		}
181100384Speter
182100384Speter		ucred = td->td_ucred;
183100384Speter		if ((error = VOP_GETATTR(nd.ni_vp, &vat, ucred, td)) != 0) {
184100384Speter			goto bad;
185100384Speter		}
186100384Speter
187100384Speter		if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, ucred,
188100384Speter		    td)) != 0) {
189100384Speter			goto bad;
190100384Speter		}
191100384Speter
192100384Speter		if (vat.va_fsid == vatroot.va_fsid &&
193100384Speter		    vat.va_fileid == vatroot.va_fileid) {
194100384Speter			error = ENOENT;
195100384Speter			goto bad;
196100384Speter		}
197100384Speter
198100384Speter	}
199100384Speter	if (sgp == NULL)
200100384Speter		*pbuf = buf;
201100384Speter	else {
202100384Speter		sz = &ptr[len] - buf;
203100384Speter		*pbuf = stackgap_alloc(sgp, sz + 1);
204100384Speter		error = copyout(buf, *pbuf, sz);
205100384Speter		free(buf, M_TEMP);
206100384Speter	}
207100384Speter
208100384Speter	vrele(nd.ni_vp);
209100384Speter	if (!cflag)
210100384Speter		vrele(ndroot.ni_vp);
211100384Speter
212100384Speter	return error;
213100384Speter
214100384Speterbad:
215100384Speter	vrele(ndroot.ni_vp);
216100384Speter	vrele(nd.ni_vp);
217100384Speter	free(buf, M_TEMP);
218100384Speter	return error;
219100384Speter}
220100384Speter
221100384Speterint
222100384Speteria32_open(struct thread *td, struct ia32_open_args *uap)
223100384Speter{
224100384Speter	caddr_t sg;
225100384Speter
226100384Speter	sg = stackgap_init();
227100384Speter	CHECKALTEXIST(td, &sg, uap->path);
228100384Speter
229100384Speter	return open(td, (struct open_args *) uap);
230100384Speter}
231100384Speter
232100384Speterint
233100384Speteria32_wait4(struct thread *td, struct ia32_wait4_args *uap)
234100384Speter{
235100384Speter	int error;
236100384Speter	caddr_t sg;
237100384Speter	struct rusage32 *rusage32, ru32;
238100384Speter	struct rusage *rusage = NULL, ru;
239100384Speter
240107849Salfred	rusage32 = uap->rusage;
241100384Speter	if (rusage32) {
242100384Speter		sg = stackgap_init();
243100384Speter		rusage = stackgap_alloc(&sg, sizeof(struct rusage));
244107849Salfred		uap->rusage = (struct rusage32 *)rusage;
245100384Speter	}
246100384Speter	error = wait4(td, (struct wait_args *)uap);
247100384Speter	if (error)
248100384Speter		return (error);
249100384Speter	if (rusage32 && (error = copyin(rusage, &ru, sizeof(ru)) == 0)) {
250100384Speter		TV_CP(ru, ru32, ru_utime);
251100384Speter		TV_CP(ru, ru32, ru_stime);
252100384Speter		CP(ru, ru32, ru_maxrss);
253100384Speter		CP(ru, ru32, ru_ixrss);
254100384Speter		CP(ru, ru32, ru_idrss);
255100384Speter		CP(ru, ru32, ru_isrss);
256100384Speter		CP(ru, ru32, ru_minflt);
257100384Speter		CP(ru, ru32, ru_majflt);
258100384Speter		CP(ru, ru32, ru_nswap);
259100384Speter		CP(ru, ru32, ru_inblock);
260100384Speter		CP(ru, ru32, ru_oublock);
261100384Speter		CP(ru, ru32, ru_msgsnd);
262100384Speter		CP(ru, ru32, ru_msgrcv);
263100384Speter		CP(ru, ru32, ru_nsignals);
264100384Speter		CP(ru, ru32, ru_nvcsw);
265100384Speter		CP(ru, ru32, ru_nivcsw);
266100384Speter		error = copyout(&ru32, rusage32, sizeof(ru32));
267100384Speter	}
268100384Speter	return (error);
269100384Speter}
270100384Speter
271100384Speterstatic void
272100384Spetercopy_statfs(struct statfs *in, struct statfs32 *out)
273100384Speter{
274100384Speter	CP(*in, *out, f_bsize);
275100384Speter	CP(*in, *out, f_iosize);
276100384Speter	CP(*in, *out, f_blocks);
277100384Speter	CP(*in, *out, f_bfree);
278100384Speter	CP(*in, *out, f_bavail);
279100384Speter	CP(*in, *out, f_files);
280100384Speter	CP(*in, *out, f_ffree);
281100384Speter	CP(*in, *out, f_fsid);
282100384Speter	CP(*in, *out, f_owner);
283100384Speter	CP(*in, *out, f_type);
284100384Speter	CP(*in, *out, f_flags);
285100384Speter	CP(*in, *out, f_flags);
286100384Speter	CP(*in, *out, f_syncwrites);
287100384Speter	CP(*in, *out, f_asyncwrites);
288100384Speter	bcopy(in->f_fstypename,
289100384Speter	      out->f_fstypename, MFSNAMELEN);
290100384Speter	bcopy(in->f_mntonname,
291100384Speter	      out->f_mntonname, MNAMELEN);
292100384Speter	CP(*in, *out, f_syncreads);
293100384Speter	CP(*in, *out, f_asyncreads);
294100384Speter	bcopy(in->f_mntfromname,
295100384Speter	      out->f_mntfromname, MNAMELEN);
296100384Speter}
297100384Speter
298100384Speterint
299100384Speteria32_getfsstat(struct thread *td, struct ia32_getfsstat_args *uap)
300100384Speter{
301100384Speter	int error;
302100384Speter	caddr_t sg;
303100384Speter	struct statfs32 *sp32, stat32;
304100384Speter	struct statfs *sp = NULL, stat;
305100384Speter	int maxcount, count, i;
306100384Speter
307107849Salfred	sp32 = uap->buf;
308107849Salfred	maxcount = uap->bufsize / sizeof(struct statfs32);
309100384Speter
310100384Speter	if (sp32) {
311100384Speter		sg = stackgap_init();
312100384Speter		sp = stackgap_alloc(&sg, sizeof(struct statfs) * maxcount);
313107849Salfred		uap->buf = (struct statfs32 *)sp;
314100384Speter	}
315100384Speter	error = getfsstat(td, (struct getfsstat_args *) uap);
316100384Speter	if (sp32 && !error) {
317100384Speter		count = td->td_retval[0];
318100384Speter		for (i = 0; i < count; i++) {
319100384Speter			error = copyin(&sp[i], &stat, sizeof(stat));
320100384Speter			if (error)
321100384Speter				return (error);
322100384Speter			copy_statfs(&stat, &stat32);
323100384Speter			error = copyout(&stat32, &sp32[i], sizeof(stat32));
324100384Speter			if (error)
325100384Speter				return (error);
326100384Speter		}
327100384Speter	}
328100384Speter	return (error);
329100384Speter}
330100384Speter
331100384Speterint
332100384Speteria32_access(struct thread *td, struct ia32_access_args *uap)
333100384Speter{
334100384Speter	caddr_t sg;
335100384Speter
336100384Speter	sg = stackgap_init();
337100384Speter	CHECKALTEXIST(td, &sg, uap->path);
338100384Speter
339100384Speter	return access(td, (struct access_args *)uap);
340100384Speter}
341100384Speter
342100384Speterint
343100384Speteria32_chflags(struct thread *td, struct ia32_chflags_args *uap)
344100384Speter{
345100384Speter	caddr_t sg;
346100384Speter
347100384Speter	sg = stackgap_init();
348100384Speter	CHECKALTEXIST(td, &sg, uap->path);
349100384Speter
350100384Speter	return chflags(td, (struct chflags_args *)uap);
351100384Speter}
352100384Speter
353100384Speterstruct sigaltstack32 {
354100384Speter	u_int32_t	ss_sp;
355100384Speter	u_int32_t	ss_size;
356100384Speter	int		ss_flags;
357100384Speter};
358100384Speter
359100384Speterint
360100384Speteria32_sigaltstack(struct thread *td, struct ia32_sigaltstack_args *uap)
361100384Speter{
362113859Sjhb	struct sigaltstack32 s32;
363113859Sjhb	struct sigaltstack ss, oss, *ssp;
364100384Speter	int error;
365100384Speter
366113859Sjhb	if (uap->ss != NULL) {
367113859Sjhb		error = copyin(uap->ss, &s32, sizeof(s32));
368100384Speter		if (error)
369100384Speter			return (error);
370113859Sjhb		PTRIN_CP(s32, ss, ss_sp);
371113859Sjhb		CP(s32, ss, ss_size);
372113859Sjhb		CP(s32, ss, ss_flags);
373113859Sjhb		ssp = &ss;
374113859Sjhb	} else
375113859Sjhb		ssp = NULL;
376113859Sjhb	error = kern_sigaltstack(td, ssp, &oss);
377113859Sjhb	if (error == 0 && uap->oss != NULL) {
378113859Sjhb		PTROUT_CP(oss, s32, ss_sp);
379113859Sjhb		CP(oss, s32, ss_size);
380113859Sjhb		CP(oss, s32, ss_flags);
381113859Sjhb		error = copyout(&s32, uap->oss, sizeof(s32));
382100384Speter	}
383100384Speter	return (error);
384100384Speter}
385100384Speter
386100384Speterint
387100384Speteria32_execve(struct thread *td, struct ia32_execve_args *uap)
388100384Speter{
389100384Speter	int error;
390100384Speter	caddr_t sg;
391100384Speter	struct execve_args ap;
392100384Speter	u_int32_t *p32, arg;
393100384Speter	char **p;
394100384Speter	int count;
395100384Speter
396100384Speter	sg = stackgap_init();
397107849Salfred	CHECKALTEXIST(td, &sg, uap->fname);
398107849Salfred	ap.fname = uap->fname;
399100384Speter
400107849Salfred	if (uap->argv) {
401100384Speter		count = 0;
402107849Salfred		p32 = uap->argv;
403100384Speter		do {
404100384Speter			error = copyin(p32++, &arg, sizeof(arg));
405100384Speter			if (error)
406100384Speter				return error;
407100384Speter			count++;
408100384Speter		} while (arg != 0);
409100384Speter		p = stackgap_alloc(&sg, count * sizeof(char *));
410107849Salfred		ap.argv = p;
411107849Salfred		p32 = uap->argv;
412100384Speter		do {
413100384Speter			error = copyin(p32++, &arg, sizeof(arg));
414100384Speter			if (error)
415100384Speter				return error;
416100384Speter			*p++ = PTRIN(arg);
417100384Speter		} while (arg != 0);
418100384Speter	}
419107849Salfred	if (uap->envv) {
420100384Speter		count = 0;
421107849Salfred		p32 = uap->envv;
422100384Speter		do {
423100384Speter			error = copyin(p32++, &arg, sizeof(arg));
424100384Speter			if (error)
425100384Speter				return error;
426100384Speter			count++;
427100384Speter		} while (arg != 0);
428100384Speter		p = stackgap_alloc(&sg, count * sizeof(char *));
429107849Salfred		ap.envv = p;
430107849Salfred		p32 = uap->envv;
431100384Speter		do {
432100384Speter			error = copyin(p32++, &arg, sizeof(arg));
433100384Speter			if (error)
434100384Speter				return error;
435100384Speter			*p++ = PTRIN(arg);
436100384Speter		} while (arg != 0);
437100384Speter	}
438100384Speter
439100384Speter	return execve(td, &ap);
440100384Speter}
441100384Speter
442114987Speter#ifdef __ia64__
443100384Speterstatic int
444100384Speteria32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
445100384Speter		  int prot, int fd, off_t pos)
446100384Speter{
447100384Speter	vm_map_t map;
448100384Speter	vm_map_entry_t entry;
449100384Speter	int rv;
450100384Speter
451100384Speter	map = &td->td_proc->p_vmspace->vm_map;
452100384Speter	if (fd != -1)
453100384Speter		prot |= VM_PROT_WRITE;
454100384Speter
455100384Speter	if (vm_map_lookup_entry(map, start, &entry)) {
456100384Speter		if ((entry->protection & prot) != prot) {
457100384Speter			rv = vm_map_protect(map,
458100384Speter					    trunc_page(start),
459100384Speter					    round_page(end),
460100384Speter					    entry->protection | prot,
461100384Speter					    FALSE);
462100384Speter			if (rv != KERN_SUCCESS)
463100384Speter				return (EINVAL);
464100384Speter		}
465100384Speter	} else {
466100384Speter		vm_offset_t addr = trunc_page(start);
467100384Speter		rv = vm_map_find(map, 0, 0,
468100384Speter				 &addr, PAGE_SIZE, FALSE, prot,
469100384Speter				 VM_PROT_ALL, 0);
470100384Speter		if (rv != KERN_SUCCESS)
471100384Speter			return (EINVAL);
472100384Speter	}
473100384Speter
474100384Speter	if (fd != -1) {
475100384Speter		struct pread_args r;
476107849Salfred		r.fd = fd;
477107849Salfred		r.buf = (void *) start;
478107849Salfred		r.nbyte = end - start;
479107849Salfred		r.offset = pos;
480100384Speter		return (pread(td, &r));
481100384Speter	} else {
482100384Speter		while (start < end) {
483100384Speter			subyte((void *) start, 0);
484100384Speter			start++;
485100384Speter		}
486100384Speter		return (0);
487100384Speter	}
488100384Speter}
489114987Speter#endif
490100384Speter
491100384Speterint
492100384Speteria32_mmap(struct thread *td, struct ia32_mmap_args *uap)
493100384Speter{
494100384Speter	struct mmap_args ap;
495107849Salfred	vm_offset_t addr = (vm_offset_t) uap->addr;
496107849Salfred	vm_size_t len	 = uap->len;
497107849Salfred	int prot	 = uap->prot;
498107849Salfred	int flags	 = uap->flags;
499107849Salfred	int fd		 = uap->fd;
500107849Salfred	off_t pos	 = (uap->poslo
501107849Salfred			    | ((off_t)uap->poshi << 32));
502114987Speter#ifdef __ia64__
503100384Speter	vm_size_t pageoff;
504100384Speter	int error;
505100384Speter
506100384Speter	/*
507100384Speter	 * Attempt to handle page size hassles.
508100384Speter	 */
509100384Speter	pageoff = (pos & PAGE_MASK);
510100384Speter	if (flags & MAP_FIXED) {
511100384Speter		vm_offset_t start, end;
512100384Speter		start = addr;
513100384Speter		end = addr + len;
514100384Speter
515100384Speter		if (start != trunc_page(start)) {
516100384Speter			error = ia32_mmap_partial(td, start, round_page(start),
517100384Speter						  prot, fd, pos);
518100384Speter			if (fd != -1)
519100384Speter				pos += round_page(start) - start;
520100384Speter			start = round_page(start);
521100384Speter		}
522100384Speter		if (end != round_page(end)) {
523100384Speter			vm_offset_t t = trunc_page(end);
524100384Speter			error = ia32_mmap_partial(td, t, end,
525100384Speter						  prot, fd,
526100384Speter						  pos + t - start);
527100384Speter			end = trunc_page(end);
528100384Speter		}
529100384Speter		if (end > start && fd != -1 && (pos & PAGE_MASK)) {
530100384Speter			/*
531100384Speter			 * We can't map this region at all. The specified
532100384Speter			 * address doesn't have the same alignment as the file
533100384Speter			 * position. Fake the mapping by simply reading the
534100384Speter			 * entire region into memory. First we need to make
535100384Speter			 * sure the region exists.
536100384Speter			 */
537100384Speter			vm_map_t map;
538100384Speter			struct pread_args r;
539100384Speter			int rv;
540100384Speter
541100384Speter			prot |= VM_PROT_WRITE;
542100384Speter			map = &td->td_proc->p_vmspace->vm_map;
543100384Speter			rv = vm_map_remove(map, start, end);
544100384Speter			if (rv != KERN_SUCCESS)
545100384Speter				return (EINVAL);
546100384Speter			rv = vm_map_find(map, 0, 0,
547100384Speter					 &start, end - start, FALSE,
548100384Speter					 prot, VM_PROT_ALL, 0);
549100384Speter			if (rv != KERN_SUCCESS)
550100384Speter				return (EINVAL);
551107849Salfred			r.fd = fd;
552107849Salfred			r.buf = (void *) start;
553107849Salfred			r.nbyte = end - start;
554107849Salfred			r.offset = pos;
555100384Speter			error = pread(td, &r);
556100384Speter			if (error)
557100384Speter				return (error);
558100384Speter
559100384Speter			td->td_retval[0] = addr;
560100384Speter			return (0);
561100384Speter		}
562100384Speter		if (end == start) {
563100384Speter			/*
564100384Speter			 * After dealing with the ragged ends, there
565100384Speter			 * might be none left.
566100384Speter			 */
567100384Speter			td->td_retval[0] = addr;
568100384Speter			return (0);
569100384Speter		}
570100384Speter		addr = start;
571100384Speter		len = end - start;
572100384Speter	}
573114987Speter#endif
574100384Speter
575107849Salfred	ap.addr = (void *) addr;
576107849Salfred	ap.len = len;
577107849Salfred	ap.prot = prot;
578107849Salfred	ap.flags = flags;
579107849Salfred	ap.fd = fd;
580107849Salfred	ap.pos = pos;
581100384Speter
582100384Speter	return (mmap(td, &ap));
583100384Speter}
584100384Speter
585100384Speterstruct itimerval32 {
586100384Speter	struct timeval32 it_interval;
587100384Speter	struct timeval32 it_value;
588100384Speter};
589100384Speter
590100384Speterint
591100384Speteria32_setitimer(struct thread *td, struct ia32_setitimer_args *uap)
592100384Speter{
593100384Speter	int error;
594100384Speter	caddr_t sg;
595100384Speter	struct itimerval32 *p32, *op32, s32;
596100384Speter	struct itimerval *p = NULL, *op = NULL, s;
597100384Speter
598107849Salfred	p32 = uap->itv;
599100384Speter	if (p32) {
600100384Speter		sg = stackgap_init();
601100384Speter		p = stackgap_alloc(&sg, sizeof(struct itimerval));
602107849Salfred		uap->itv = (struct itimerval32 *)p;
603100384Speter		error = copyin(p32, &s32, sizeof(s32));
604100384Speter		if (error)
605100384Speter			return (error);
606100384Speter		TV_CP(s32, s, it_interval);
607100384Speter		TV_CP(s32, s, it_value);
608100384Speter		error = copyout(&s, p, sizeof(s));
609100384Speter		if (error)
610100384Speter			return (error);
611100384Speter	}
612107849Salfred	op32 = uap->oitv;
613100384Speter	if (op32) {
614100384Speter		sg = stackgap_init();
615100384Speter		op = stackgap_alloc(&sg, sizeof(struct itimerval));
616107849Salfred		uap->oitv = (struct itimerval32 *)op;
617100384Speter	}
618100384Speter	error = setitimer(td, (struct setitimer_args *) uap);
619100384Speter	if (error)
620100384Speter		return (error);
621100384Speter	if (op32) {
622100384Speter		error = copyin(op, &s, sizeof(s));
623100384Speter		if (error)
624100384Speter			return (error);
625100384Speter		TV_CP(s, s32, it_interval);
626100384Speter		TV_CP(s, s32, it_value);
627100384Speter		error = copyout(&s32, op32, sizeof(s32));
628100384Speter	}
629100384Speter	return (error);
630100384Speter}
631100384Speter
632100384Speterint
633100384Speteria32_select(struct thread *td, struct ia32_select_args *uap)
634100384Speter{
635100384Speter	int error;
636100384Speter	caddr_t sg;
637100384Speter	struct timeval32 *p32, s32;
638100384Speter	struct timeval *p = NULL, s;
639100384Speter
640107849Salfred	p32 = uap->tv;
641100384Speter	if (p32) {
642100384Speter		sg = stackgap_init();
643100384Speter		p = stackgap_alloc(&sg, sizeof(struct timeval));
644107849Salfred		uap->tv = (struct timeval32 *)p;
645100384Speter		error = copyin(p32, &s32, sizeof(s32));
646100384Speter		if (error)
647100384Speter			return (error);
648100384Speter		CP(s32, s, tv_sec);
649100384Speter		CP(s32, s, tv_usec);
650100384Speter		error = copyout(&s, p, sizeof(s));
651100384Speter		if (error)
652100384Speter			return (error);
653100384Speter	}
654100384Speter	/*
655100384Speter	 * XXX big-endian needs to convert the fd_sets too.
656100384Speter	 */
657100384Speter	return (select(td, (struct select_args *) uap));
658100384Speter}
659100384Speter
660114987Speterstruct kevent32 {
661114987Speter	u_int32_t	ident;		/* identifier for this event */
662114987Speter	short		filter;		/* filter for event */
663114987Speter	u_short		flags;
664114987Speter	u_int		fflags;
665114987Speter	int32_t		data;
666114987Speter	u_int32_t	udata;		/* opaque user data identifier */
667114987Speter};
668114987Speter
669100384Speterint
670114987Speteria32_kevent(struct thread *td, struct ia32_kevent_args *uap)
671114987Speter{
672114987Speter	int error;
673114987Speter	caddr_t sg;
674114987Speter	struct timespec32 ts32;
675114987Speter	struct timespec ts;
676114987Speter	struct kevent32 ks32;
677114987Speter	struct kevent *ks;
678114987Speter	struct kevent_args a;
679114987Speter	int i;
680114987Speter
681114987Speter	sg = stackgap_init();
682114987Speter
683114987Speter	a.fd = uap->fd;
684114987Speter	a.changelist = uap->changelist;
685114987Speter	a.nchanges = uap->nchanges;
686114987Speter	a.eventlist = uap->eventlist;
687114987Speter	a.nevents = uap->nevents;
688114987Speter	a.timeout = NULL;
689114987Speter
690114987Speter	if (uap->timeout) {
691114987Speter		a.timeout = stackgap_alloc(&sg, sizeof(struct timespec));
692114987Speter		error = copyin(uap->timeout, &ts32, sizeof(ts32));
693114987Speter		if (error)
694114987Speter			return (error);
695114987Speter		CP(ts32, ts, tv_sec);
696114987Speter		CP(ts32, ts, tv_nsec);
697114987Speter		error = copyout(&ts, (void *)(uintptr_t)a.timeout, sizeof(ts));
698114987Speter		if (error)
699114987Speter			return (error);
700114987Speter	}
701114987Speter	if (uap->changelist) {
702114987Speter		a.changelist = (struct kevent *)stackgap_alloc(&sg, uap->nchanges * sizeof(struct kevent));
703114987Speter		for (i = 0; i < uap->nchanges; i++) {
704114987Speter			error = copyin(&uap->changelist[i], &ks32, sizeof(ks32));
705114987Speter			if (error)
706114987Speter				return (error);
707114987Speter			ks = (struct kevent *)(uintptr_t)&a.changelist[i];
708114987Speter			CP(ks32, *ks, ident);
709114987Speter			CP(ks32, *ks, filter);
710114987Speter			CP(ks32, *ks, flags);
711114987Speter			CP(ks32, *ks, fflags);
712114987Speter			CP(ks32, *ks, data);
713114987Speter			PTRIN_CP(ks32, *ks, udata);
714114987Speter		}
715114987Speter	}
716114987Speter	if (uap->eventlist) {
717114987Speter		a.eventlist = stackgap_alloc(&sg, uap->nevents * sizeof(struct kevent));
718114987Speter	}
719114987Speter	error = kevent(td, &a);
720114987Speter	if (uap->eventlist && error > 0) {
721114987Speter		for (i = 0; i < error; i++) {
722114987Speter			ks = &a.eventlist[i];
723114987Speter			CP(*ks, ks32, ident);
724114987Speter			CP(*ks, ks32, filter);
725114987Speter			CP(*ks, ks32, flags);
726114987Speter			CP(*ks, ks32, fflags);
727114987Speter			CP(*ks, ks32, data);
728114987Speter			PTROUT_CP(*ks, ks32, udata);
729114987Speter			error = copyout(&ks32, &uap->eventlist[i], sizeof(ks32));
730114987Speter			if (error)
731114987Speter				return (error);
732114987Speter		}
733114987Speter	}
734114987Speter	return error;
735114987Speter}
736114987Speter
737114987Speterint
738100384Speteria32_gettimeofday(struct thread *td, struct ia32_gettimeofday_args *uap)
739100384Speter{
740100384Speter	int error;
741100384Speter	caddr_t sg;
742100384Speter	struct timeval32 *p32, s32;
743100384Speter	struct timeval *p = NULL, s;
744100384Speter
745107849Salfred	p32 = uap->tp;
746100384Speter	if (p32) {
747100384Speter		sg = stackgap_init();
748100384Speter		p = stackgap_alloc(&sg, sizeof(struct timeval));
749107849Salfred		uap->tp = (struct timeval32 *)p;
750100384Speter	}
751100384Speter	error = gettimeofday(td, (struct gettimeofday_args *) uap);
752100384Speter	if (error)
753100384Speter		return (error);
754100384Speter	if (p32) {
755100384Speter		error = copyin(p, &s, sizeof(s));
756100384Speter		if (error)
757100384Speter			return (error);
758100384Speter		CP(s, s32, tv_sec);
759100384Speter		CP(s, s32, tv_usec);
760100384Speter		error = copyout(&s32, p32, sizeof(s32));
761100384Speter		if (error)
762100384Speter			return (error);
763100384Speter	}
764100384Speter	return (error);
765100384Speter}
766100384Speter
767100384Speterint
768100384Speteria32_getrusage(struct thread *td, struct ia32_getrusage_args *uap)
769100384Speter{
770100384Speter	int error;
771100384Speter	caddr_t sg;
772100384Speter	struct rusage32 *p32, s32;
773100384Speter	struct rusage *p = NULL, s;
774100384Speter
775107849Salfred	p32 = uap->rusage;
776100384Speter	if (p32) {
777100384Speter		sg = stackgap_init();
778100384Speter		p = stackgap_alloc(&sg, sizeof(struct rusage));
779107849Salfred		uap->rusage = (struct rusage32 *)p;
780100384Speter	}
781100384Speter	error = getrusage(td, (struct getrusage_args *) uap);
782100384Speter	if (error)
783100384Speter		return (error);
784100384Speter	if (p32) {
785100384Speter		error = copyin(p, &s, sizeof(s));
786100384Speter		if (error)
787100384Speter			return (error);
788100384Speter		TV_CP(s, s32, ru_utime);
789100384Speter		TV_CP(s, s32, ru_stime);
790100384Speter		CP(s, s32, ru_maxrss);
791100384Speter		CP(s, s32, ru_ixrss);
792100384Speter		CP(s, s32, ru_idrss);
793100384Speter		CP(s, s32, ru_isrss);
794100384Speter		CP(s, s32, ru_minflt);
795100384Speter		CP(s, s32, ru_majflt);
796100384Speter		CP(s, s32, ru_nswap);
797100384Speter		CP(s, s32, ru_inblock);
798100384Speter		CP(s, s32, ru_oublock);
799100384Speter		CP(s, s32, ru_msgsnd);
800100384Speter		CP(s, s32, ru_msgrcv);
801100384Speter		CP(s, s32, ru_nsignals);
802100384Speter		CP(s, s32, ru_nvcsw);
803100384Speter		CP(s, s32, ru_nivcsw);
804100384Speter		error = copyout(&s32, p32, sizeof(s32));
805100384Speter	}
806100384Speter	return (error);
807100384Speter}
808100384Speter
809100384Speterstruct iovec32 {
810100384Speter	u_int32_t iov_base;
811100384Speter	int	iov_len;
812100384Speter};
813100384Speter#define	STACKGAPLEN	400
814100384Speter
815100384Speterint
816100384Speteria32_readv(struct thread *td, struct ia32_readv_args *uap)
817100384Speter{
818100384Speter	int error, osize, nsize, i;
819100384Speter	caddr_t sg;
820100384Speter	struct readv_args /* {
821100384Speter		syscallarg(int) fd;
822100384Speter		syscallarg(struct iovec *) iovp;
823100384Speter		syscallarg(u_int) iovcnt;
824100384Speter	} */ a;
825100384Speter	struct iovec32 *oio;
826100384Speter	struct iovec *nio;
827100384Speter
828100384Speter	sg = stackgap_init();
829100384Speter
830107849Salfred	if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
831100384Speter		return (EINVAL);
832100384Speter
833107849Salfred	osize = uap->iovcnt * sizeof (struct iovec32);
834107849Salfred	nsize = uap->iovcnt * sizeof (struct iovec);
835100384Speter
836111119Simp	oio = malloc(osize, M_TEMP, M_WAITOK);
837111119Simp	nio = malloc(nsize, M_TEMP, M_WAITOK);
838100384Speter
839100384Speter	error = 0;
840107849Salfred	if ((error = copyin(uap->iovp, oio, osize)))
841100384Speter		goto punt;
842107849Salfred	for (i = 0; i < uap->iovcnt; i++) {
843100384Speter		nio[i].iov_base = PTRIN(oio[i].iov_base);
844100384Speter		nio[i].iov_len = oio[i].iov_len;
845100384Speter	}
846100384Speter
847107849Salfred	a.fd = uap->fd;
848107849Salfred	a.iovp = stackgap_alloc(&sg, nsize);
849107849Salfred	a.iovcnt = uap->iovcnt;
850100384Speter
851107849Salfred	if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
852100384Speter		goto punt;
853100384Speter	error = readv(td, &a);
854100384Speter
855100384Speterpunt:
856100384Speter	free(oio, M_TEMP);
857100384Speter	free(nio, M_TEMP);
858100384Speter	return (error);
859100384Speter}
860100384Speter
861100384Speterint
862100384Speteria32_writev(struct thread *td, struct ia32_writev_args *uap)
863100384Speter{
864100384Speter	int error, i, nsize, osize;
865100384Speter	caddr_t sg;
866100384Speter	struct writev_args /* {
867100384Speter		syscallarg(int) fd;
868100384Speter		syscallarg(struct iovec *) iovp;
869100384Speter		syscallarg(u_int) iovcnt;
870100384Speter	} */ a;
871100384Speter	struct iovec32 *oio;
872100384Speter	struct iovec *nio;
873100384Speter
874100384Speter	sg = stackgap_init();
875100384Speter
876107849Salfred	if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
877100384Speter		return (EINVAL);
878100384Speter
879107849Salfred	osize = uap->iovcnt * sizeof (struct iovec32);
880107849Salfred	nsize = uap->iovcnt * sizeof (struct iovec);
881100384Speter
882111119Simp	oio = malloc(osize, M_TEMP, M_WAITOK);
883111119Simp	nio = malloc(nsize, M_TEMP, M_WAITOK);
884100384Speter
885100384Speter	error = 0;
886107849Salfred	if ((error = copyin(uap->iovp, oio, osize)))
887100384Speter		goto punt;
888107849Salfred	for (i = 0; i < uap->iovcnt; i++) {
889100384Speter		nio[i].iov_base = PTRIN(oio[i].iov_base);
890100384Speter		nio[i].iov_len = oio[i].iov_len;
891100384Speter	}
892100384Speter
893107849Salfred	a.fd = uap->fd;
894107849Salfred	a.iovp = stackgap_alloc(&sg, nsize);
895107849Salfred	a.iovcnt = uap->iovcnt;
896100384Speter
897107849Salfred	if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
898100384Speter		goto punt;
899100384Speter	error = writev(td, &a);
900100384Speter
901100384Speterpunt:
902100384Speter	free(oio, M_TEMP);
903100384Speter	free(nio, M_TEMP);
904100384Speter	return (error);
905100384Speter}
906100384Speter
907100384Speterint
908100384Speteria32_settimeofday(struct thread *td, struct ia32_settimeofday_args *uap)
909100384Speter{
910100384Speter	int error;
911100384Speter	caddr_t sg;
912100384Speter	struct timeval32 *p32, s32;
913100384Speter	struct timeval *p = NULL, s;
914100384Speter
915107849Salfred	p32 = uap->tv;
916100384Speter	if (p32) {
917100384Speter		sg = stackgap_init();
918100384Speter		p = stackgap_alloc(&sg, sizeof(struct timeval));
919107849Salfred		uap->tv = (struct timeval32 *)p;
920100384Speter		error = copyin(p32, &s32, sizeof(s32));
921100384Speter		if (error)
922100384Speter			return (error);
923100384Speter		CP(s32, s, tv_sec);
924100384Speter		CP(s32, s, tv_usec);
925100384Speter		error = copyout(&s, p, sizeof(s));
926100384Speter		if (error)
927100384Speter			return (error);
928100384Speter	}
929100384Speter	return (settimeofday(td, (struct settimeofday_args *) uap));
930100384Speter}
931100384Speter
932100384Speterint
933100384Speteria32_utimes(struct thread *td, struct ia32_utimes_args *uap)
934100384Speter{
935100384Speter	int error;
936100384Speter	caddr_t sg;
937100384Speter	struct timeval32 *p32, s32[2];
938100384Speter	struct timeval *p = NULL, s[2];
939100384Speter
940107849Salfred	p32 = uap->tptr;
941100384Speter	if (p32) {
942100384Speter		sg = stackgap_init();
943100384Speter		p = stackgap_alloc(&sg, 2*sizeof(struct timeval));
944107849Salfred		uap->tptr = (struct timeval32 *)p;
945100384Speter		error = copyin(p32, s32, sizeof(s32));
946100384Speter		if (error)
947100384Speter			return (error);
948100384Speter		CP(s32[0], s[0], tv_sec);
949100384Speter		CP(s32[0], s[0], tv_usec);
950100384Speter		CP(s32[1], s[1], tv_sec);
951100384Speter		CP(s32[1], s[1], tv_usec);
952100384Speter		error = copyout(s, p, sizeof(s));
953100384Speter		if (error)
954100384Speter			return (error);
955100384Speter	}
956100384Speter	return (utimes(td, (struct utimes_args *) uap));
957100384Speter}
958100384Speter
959100384Speterint
960100384Speteria32_adjtime(struct thread *td, struct ia32_adjtime_args *uap)
961100384Speter{
962100384Speter	int error;
963100384Speter	caddr_t sg;
964100384Speter	struct timeval32 *p32, *op32, s32;
965100384Speter	struct timeval *p = NULL, *op = NULL, s;
966100384Speter
967107849Salfred	p32 = uap->delta;
968100384Speter	if (p32) {
969100384Speter		sg = stackgap_init();
970100384Speter		p = stackgap_alloc(&sg, sizeof(struct timeval));
971107849Salfred		uap->delta = (struct timeval32 *)p;
972100384Speter		error = copyin(p32, &s32, sizeof(s32));
973100384Speter		if (error)
974100384Speter			return (error);
975100384Speter		CP(s32, s, tv_sec);
976100384Speter		CP(s32, s, tv_usec);
977100384Speter		error = copyout(&s, p, sizeof(s));
978100384Speter		if (error)
979100384Speter			return (error);
980100384Speter	}
981107849Salfred	op32 = uap->olddelta;
982100384Speter	if (op32) {
983100384Speter		sg = stackgap_init();
984100384Speter		op = stackgap_alloc(&sg, sizeof(struct timeval));
985107849Salfred		uap->olddelta = (struct timeval32 *)op;
986100384Speter	}
987100384Speter	error = utimes(td, (struct utimes_args *) uap);
988100384Speter	if (error)
989100384Speter		return error;
990100384Speter	if (op32) {
991100384Speter		error = copyin(op, &s, sizeof(s));
992100384Speter		if (error)
993100384Speter			return (error);
994100384Speter		CP(s, s32, tv_sec);
995100384Speter		CP(s, s32, tv_usec);
996100384Speter		error = copyout(&s32, op32, sizeof(s32));
997100384Speter	}
998100384Speter	return (error);
999100384Speter}
1000100384Speter
1001100384Speterint
1002100384Speteria32_statfs(struct thread *td, struct ia32_statfs_args *uap)
1003100384Speter{
1004100384Speter	int error;
1005100384Speter	caddr_t sg;
1006100384Speter	struct statfs32 *p32, s32;
1007100384Speter	struct statfs *p = NULL, s;
1008100384Speter
1009107849Salfred	p32 = uap->buf;
1010100384Speter	if (p32) {
1011100384Speter		sg = stackgap_init();
1012100384Speter		p = stackgap_alloc(&sg, sizeof(struct statfs));
1013107849Salfred		uap->buf = (struct statfs32 *)p;
1014100384Speter	}
1015100384Speter	error = statfs(td, (struct statfs_args *) uap);
1016100384Speter	if (error)
1017100384Speter		return (error);
1018100384Speter	if (p32) {
1019100384Speter		error = copyin(p, &s, sizeof(s));
1020100384Speter		if (error)
1021100384Speter			return (error);
1022100384Speter		copy_statfs(&s, &s32);
1023100384Speter		error = copyout(&s32, p32, sizeof(s32));
1024100384Speter	}
1025100384Speter	return (error);
1026100384Speter}
1027100384Speter
1028100384Speterint
1029100384Speteria32_fstatfs(struct thread *td, struct ia32_fstatfs_args *uap)
1030100384Speter{
1031100384Speter	int error;
1032100384Speter	caddr_t sg;
1033100384Speter	struct statfs32 *p32, s32;
1034100384Speter	struct statfs *p = NULL, s;
1035100384Speter
1036107849Salfred	p32 = uap->buf;
1037100384Speter	if (p32) {
1038100384Speter		sg = stackgap_init();
1039100384Speter		p = stackgap_alloc(&sg, sizeof(struct statfs));
1040107849Salfred		uap->buf = (struct statfs32 *)p;
1041100384Speter	}
1042100384Speter	error = fstatfs(td, (struct fstatfs_args *) uap);
1043100384Speter	if (error)
1044100384Speter		return (error);
1045100384Speter	if (p32) {
1046100384Speter		error = copyin(p, &s, sizeof(s));
1047100384Speter		if (error)
1048100384Speter			return (error);
1049100384Speter		copy_statfs(&s, &s32);
1050100384Speter		error = copyout(&s32, p32, sizeof(s32));
1051100384Speter	}
1052100384Speter	return (error);
1053100384Speter}
1054100384Speter
1055100384Speterint
1056100384Speteria32_semsys(struct thread *td, struct ia32_semsys_args *uap)
1057100384Speter{
1058100384Speter	/*
1059100384Speter	 * Vector through to semsys if it is loaded.
1060100384Speter	 */
1061100384Speter	return sysent[169].sy_call(td, uap);
1062100384Speter}
1063100384Speter
1064100384Speterint
1065100384Speteria32_msgsys(struct thread *td, struct ia32_msgsys_args *uap)
1066100384Speter{
1067100384Speter	/*
1068100384Speter	 * Vector through to msgsys if it is loaded.
1069100384Speter	 */
1070100384Speter	return sysent[170].sy_call(td, uap);
1071100384Speter}
1072100384Speter
1073100384Speterint
1074100384Speteria32_shmsys(struct thread *td, struct ia32_shmsys_args *uap)
1075100384Speter{
1076100384Speter	/*
1077100384Speter	 * Vector through to shmsys if it is loaded.
1078100384Speter	 */
1079100384Speter	return sysent[171].sy_call(td, uap);
1080100384Speter}
1081100384Speter
1082100384Speterint
1083100384Speteria32_pread(struct thread *td, struct ia32_pread_args *uap)
1084100384Speter{
1085100384Speter	struct pread_args ap;
1086100384Speter
1087107849Salfred	ap.fd = uap->fd;
1088107849Salfred	ap.buf = uap->buf;
1089107849Salfred	ap.nbyte = uap->nbyte;
1090107849Salfred	ap.offset = (uap->offsetlo
1091107849Salfred			      | ((off_t)uap->offsethi << 32));
1092100384Speter	return (pread(td, &ap));
1093100384Speter}
1094100384Speter
1095100384Speterint
1096100384Speteria32_pwrite(struct thread *td, struct ia32_pwrite_args *uap)
1097100384Speter{
1098100384Speter	struct pwrite_args ap;
1099100384Speter
1100107849Salfred	ap.fd = uap->fd;
1101107849Salfred	ap.buf = uap->buf;
1102107849Salfred	ap.nbyte = uap->nbyte;
1103107849Salfred	ap.offset = (uap->offsetlo
1104107849Salfred			      | ((off_t)uap->offsethi << 32));
1105100384Speter	return (pwrite(td, &ap));
1106100384Speter}
1107100384Speter
1108100384Speterint
1109100384Speteria32_lseek(struct thread *td, struct ia32_lseek_args *uap)
1110100384Speter{
1111100384Speter	int error;
1112100384Speter	struct lseek_args ap;
1113100384Speter	off_t pos;
1114100384Speter
1115107849Salfred	ap.fd = uap->fd;
1116107849Salfred	ap.offset = (uap->offsetlo
1117107849Salfred			      | ((off_t)uap->offsethi << 32));
1118107849Salfred	ap.whence = uap->whence;
1119100384Speter	error = lseek(td, &ap);
1120100384Speter	/* Expand the quad return into two parts for eax and edx */
1121100384Speter	pos = *(off_t *)(td->td_retval);
1122100384Speter	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
1123100384Speter	td->td_retval[1] = pos >> 32;		/* %edx */
1124100384Speter	return error;
1125100384Speter}
1126100384Speter
1127100384Speterint
1128100384Speteria32_truncate(struct thread *td, struct ia32_truncate_args *uap)
1129100384Speter{
1130100384Speter	struct truncate_args ap;
1131100384Speter
1132107849Salfred	ap.path = uap->path;
1133107849Salfred	ap.length = (uap->lengthlo
1134107849Salfred			      | ((off_t)uap->lengthhi << 32));
1135100384Speter	return (truncate(td, &ap));
1136100384Speter}
1137100384Speter
1138100384Speterint
1139100384Speteria32_ftruncate(struct thread *td, struct ia32_ftruncate_args *uap)
1140100384Speter{
1141100384Speter	struct ftruncate_args ap;
1142100384Speter
1143107849Salfred	ap.fd = uap->fd;
1144107849Salfred	ap.length = (uap->lengthlo
1145107849Salfred			      | ((off_t)uap->lengthhi << 32));
1146100384Speter	return (ftruncate(td, &ap));
1147100384Speter}
1148100384Speter
1149104738Speter#ifdef COMPAT_FREEBSD4
1150100384Speterint
1151104738Speterfreebsd4_ia32_sendfile(struct thread *td,
1152104738Speter    struct freebsd4_ia32_sendfile_args *uap)
1153104738Speter{
1154104738Speter	struct freebsd4_sendfile_args ap;
1155104738Speter
1156107849Salfred	ap.fd = uap->fd;
1157107849Salfred	ap.s = uap->s;
1158107849Salfred	ap.offset = (uap->offsetlo
1159107849Salfred			      | ((off_t)uap->offsethi << 32));
1160107849Salfred	ap.nbytes = uap->nbytes;	/* XXX check */
1161107849Salfred	ap.hdtr = uap->hdtr;		/* XXX check */
1162107849Salfred	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1163107849Salfred	ap.flags = uap->flags;
1164104738Speter	return (freebsd4_sendfile(td, &ap));
1165104738Speter}
1166104738Speter#endif
1167104738Speter
1168104738Speterint
1169100384Speteria32_sendfile(struct thread *td, struct ia32_sendfile_args *uap)
1170100384Speter{
1171100384Speter	struct sendfile_args ap;
1172100384Speter
1173107849Salfred	ap.fd = uap->fd;
1174107849Salfred	ap.s = uap->s;
1175107849Salfred	ap.offset = (uap->offsetlo
1176107849Salfred			      | ((off_t)uap->offsethi << 32));
1177107849Salfred	ap.nbytes = uap->nbytes;	/* XXX check */
1178107849Salfred	ap.hdtr = uap->hdtr;		/* XXX check */
1179107849Salfred	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1180107849Salfred	ap.flags = uap->flags;
1181100384Speter	return (sendfile(td, &ap));
1182100384Speter}
1183100384Speter
1184100384Speterstruct stat32 {
1185100384Speter	udev_t	st_dev;
1186100384Speter	ino_t	st_ino;
1187100384Speter	mode_t	st_mode;
1188100384Speter	nlink_t	st_nlink;
1189100384Speter	uid_t	st_uid;
1190100384Speter	gid_t	st_gid;
1191100384Speter	udev_t	st_rdev;
1192100384Speter	struct timespec32 st_atimespec;
1193100384Speter	struct timespec32 st_mtimespec;
1194100384Speter	struct timespec32 st_ctimespec;
1195100384Speter	off_t	st_size;
1196100384Speter	int64_t	st_blocks;
1197100384Speter	u_int32_t st_blksize;
1198100384Speter	u_int32_t st_flags;
1199100384Speter	u_int32_t st_gen;
1200100384Speter};
1201100384Speter
1202100384Speterstatic void
1203100384Spetercopy_stat( struct stat *in, struct stat32 *out)
1204100384Speter{
1205100384Speter	CP(*in, *out, st_dev);
1206100384Speter	CP(*in, *out, st_ino);
1207100384Speter	CP(*in, *out, st_mode);
1208100384Speter	CP(*in, *out, st_nlink);
1209100384Speter	CP(*in, *out, st_uid);
1210100384Speter	CP(*in, *out, st_gid);
1211100384Speter	CP(*in, *out, st_rdev);
1212100384Speter	TS_CP(*in, *out, st_atimespec);
1213100384Speter	TS_CP(*in, *out, st_mtimespec);
1214100384Speter	TS_CP(*in, *out, st_ctimespec);
1215100384Speter	CP(*in, *out, st_size);
1216100384Speter	CP(*in, *out, st_blocks);
1217100384Speter	CP(*in, *out, st_blksize);
1218100384Speter	CP(*in, *out, st_flags);
1219100384Speter	CP(*in, *out, st_gen);
1220100384Speter}
1221100384Speter
1222100384Speterint
1223100384Speteria32_stat(struct thread *td, struct ia32_stat_args *uap)
1224100384Speter{
1225100384Speter	int error;
1226100384Speter	caddr_t sg;
1227100384Speter	struct stat32 *p32, s32;
1228100384Speter	struct stat *p = NULL, s;
1229100384Speter
1230107849Salfred	p32 = uap->ub;
1231100384Speter	if (p32) {
1232100384Speter		sg = stackgap_init();
1233100384Speter		p = stackgap_alloc(&sg, sizeof(struct stat));
1234107849Salfred		uap->ub = (struct stat32 *)p;
1235100384Speter	}
1236100384Speter	error = stat(td, (struct stat_args *) uap);
1237100384Speter	if (error)
1238100384Speter		return (error);
1239100384Speter	if (p32) {
1240100384Speter		error = copyin(p, &s, sizeof(s));
1241100384Speter		if (error)
1242100384Speter			return (error);
1243100384Speter		copy_stat(&s, &s32);
1244100384Speter		error = copyout(&s32, p32, sizeof(s32));
1245100384Speter	}
1246100384Speter	return (error);
1247100384Speter}
1248100384Speter
1249100384Speterint
1250100384Speteria32_fstat(struct thread *td, struct ia32_fstat_args *uap)
1251100384Speter{
1252100384Speter	int error;
1253100384Speter	caddr_t sg;
1254100384Speter	struct stat32 *p32, s32;
1255100384Speter	struct stat *p = NULL, s;
1256100384Speter
1257107849Salfred	p32 = uap->ub;
1258100384Speter	if (p32) {
1259100384Speter		sg = stackgap_init();
1260100384Speter		p = stackgap_alloc(&sg, sizeof(struct stat));
1261107849Salfred		uap->ub = (struct stat32 *)p;
1262100384Speter	}
1263100384Speter	error = fstat(td, (struct fstat_args *) uap);
1264100384Speter	if (error)
1265100384Speter		return (error);
1266100384Speter	if (p32) {
1267100384Speter		error = copyin(p, &s, sizeof(s));
1268100384Speter		if (error)
1269100384Speter			return (error);
1270100384Speter		copy_stat(&s, &s32);
1271100384Speter		error = copyout(&s32, p32, sizeof(s32));
1272100384Speter	}
1273100384Speter	return (error);
1274100384Speter}
1275100384Speter
1276100384Speterint
1277100384Speteria32_lstat(struct thread *td, struct ia32_lstat_args *uap)
1278100384Speter{
1279100384Speter	int error;
1280100384Speter	caddr_t sg;
1281100384Speter	struct stat32 *p32, s32;
1282100384Speter	struct stat *p = NULL, s;
1283100384Speter
1284107849Salfred	p32 = uap->ub;
1285100384Speter	if (p32) {
1286100384Speter		sg = stackgap_init();
1287100384Speter		p = stackgap_alloc(&sg, sizeof(struct stat));
1288107849Salfred		uap->ub = (struct stat32 *)p;
1289100384Speter	}
1290100384Speter	error = lstat(td, (struct lstat_args *) uap);
1291100384Speter	if (error)
1292100384Speter		return (error);
1293100384Speter	if (p32) {
1294100384Speter		error = copyin(p, &s, sizeof(s));
1295100384Speter		if (error)
1296100384Speter			return (error);
1297100384Speter		copy_stat(&s, &s32);
1298100384Speter		error = copyout(&s32, p32, sizeof(s32));
1299100384Speter	}
1300100384Speter	return (error);
1301100384Speter}
1302100384Speter
1303100384Speter/*
1304100384Speter * MPSAFE
1305100384Speter */
1306100384Speterint
1307100384Speteria32_sysctl(struct thread *td, struct ia32_sysctl_args *uap)
1308100384Speter{
1309100384Speter	int error, name[CTL_MAXNAME];
1310100384Speter	size_t j, oldlen;
1311100384Speter
1312100384Speter	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1313100384Speter		return (EINVAL);
1314100384Speter
1315100384Speter 	error = copyin(uap->name, &name, uap->namelen * sizeof(int));
1316100384Speter 	if (error)
1317100384Speter		return (error);
1318100384Speter
1319100384Speter	mtx_lock(&Giant);
1320100384Speter
1321100384Speter	if (uap->oldlenp)
1322100384Speter		oldlen = fuword32(uap->oldlenp);
1323100384Speter	else
1324100384Speter		oldlen = 0;
1325100384Speter	error = userland_sysctl(td, name, uap->namelen,
1326100384Speter		uap->old, &oldlen, 1,
1327100384Speter		uap->new, uap->newlen, &j);
1328100384Speter	if (error && error != ENOMEM)
1329100384Speter		goto done2;
1330100384Speter	if (uap->oldlenp) {
1331100384Speter		suword32(uap->oldlenp, j);
1332100384Speter	}
1333100384Speterdone2:
1334100384Speter	mtx_unlock(&Giant);
1335100384Speter	return (error);
1336100384Speter}
1337100384Speter
1338100384Speterstruct sigaction32 {
1339100384Speter	u_int32_t	sa_u;
1340100384Speter	int		sa_flags;
1341100384Speter	sigset_t	sa_mask;
1342100384Speter};
1343100384Speter
1344100384Speterint
1345100384Speteria32_sigaction(struct thread *td, struct ia32_sigaction_args *uap)
1346100384Speter{
1347113859Sjhb	struct sigaction32 s32;
1348113859Sjhb	struct sigaction sa, osa, *sap;
1349100384Speter	int error;
1350100384Speter
1351113859Sjhb	if (uap->act) {
1352113859Sjhb		error = copyin(uap->act, &s32, sizeof(s32));
1353100384Speter		if (error)
1354100384Speter			return (error);
1355113859Sjhb		sa.sa_handler = PTRIN(s32.sa_u);
1356113859Sjhb		CP(s32, sa, sa_flags);
1357113859Sjhb		CP(s32, sa, sa_mask);
1358113859Sjhb		sap = &sa;
1359113859Sjhb	} else
1360113859Sjhb		sap = NULL;
1361113859Sjhb	error = kern_sigaction(td, uap->sig, sap, &osa, 0);
1362113859Sjhb	if (error != 0 && uap->oact != NULL) {
1363113859Sjhb		s32.sa_u = PTROUT(osa.sa_handler);
1364113859Sjhb		CP(osa, s32, sa_flags);
1365113859Sjhb		CP(osa, s32, sa_mask);
1366113859Sjhb		error = copyout(&s32, uap->oact, sizeof(s32));
1367100384Speter	}
1368100384Speter	return (error);
1369100384Speter}
1370100384Speter
1371114987Speter#ifdef COMPAT_FREEBSD4
1372114987Speterint
1373114987Speterfreebsd4_ia32_sigaction(struct thread *td, struct freebsd4_ia32_sigaction_args *uap)
1374114987Speter{
1375114987Speter	struct sigaction32 s32;
1376114987Speter	struct sigaction sa, osa, *sap;
1377114987Speter	int error;
1378114987Speter
1379114987Speter	if (uap->act) {
1380114987Speter		error = copyin(uap->act, &s32, sizeof(s32));
1381114987Speter		if (error)
1382114987Speter			return (error);
1383114987Speter		sa.sa_handler = PTRIN(s32.sa_u);
1384114987Speter		CP(s32, sa, sa_flags);
1385114987Speter		CP(s32, sa, sa_mask);
1386114987Speter		sap = &sa;
1387114987Speter	} else
1388114987Speter		sap = NULL;
1389114987Speter	error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
1390114987Speter	if (error != 0 && uap->oact != NULL) {
1391114987Speter		s32.sa_u = PTROUT(osa.sa_handler);
1392114987Speter		CP(osa, s32, sa_flags);
1393114987Speter		CP(osa, s32, sa_mask);
1394114987Speter		error = copyout(&s32, uap->oact, sizeof(s32));
1395114987Speter	}
1396114987Speter	return (error);
1397114987Speter}
1398114987Speter#endif
1399114987Speter
1400100384Speter#if 0
1401100384Speter
1402100384Speterint
1403100384Speteria32_xxx(struct thread *td, struct ia32_xxx_args *uap)
1404100384Speter{
1405100384Speter	int error;
1406100384Speter	caddr_t sg;
1407100384Speter	struct yyy32 *p32, s32;
1408100384Speter	struct yyy *p = NULL, s;
1409100384Speter
1410107849Salfred	p32 = uap->zzz;
1411100384Speter	if (p32) {
1412100384Speter		sg = stackgap_init();
1413100384Speter		p = stackgap_alloc(&sg, sizeof(struct yyy));
1414107849Salfred		uap->zzz = (struct yyy32 *)p;
1415100384Speter		error = copyin(p32, &s32, sizeof(s32));
1416100384Speter		if (error)
1417100384Speter			return (error);
1418100384Speter		/* translate in */
1419100384Speter		error = copyout(&s, p, sizeof(s));
1420100384Speter		if (error)
1421100384Speter			return (error);
1422100384Speter	}
1423100384Speter	error = xxx(td, (struct xxx_args *) uap);
1424100384Speter	if (error)
1425100384Speter		return (error);
1426100384Speter	if (p32) {
1427100384Speter		error = copyin(p, &s, sizeof(s));
1428100384Speter		if (error)
1429100384Speter			return (error);
1430100384Speter		/* translate out */
1431100384Speter		error = copyout(&s32, p32, sizeof(s32));
1432100384Speter	}
1433100384Speter	return (error);
1434100384Speter}
1435100384Speter
1436100384Speter#endif
1437