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