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