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