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