xref: /freebsd/sys/compat/freebsd32/freebsd32_misc.c (revision 2b743a9e9ddc6736208dc8ca1ce06ce64ad20a19)
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 
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29 
30 #include "opt_compat.h"
31 
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/bus.h>
35 #include <sys/clock.h>
36 #include <sys/exec.h>
37 #include <sys/fcntl.h>
38 #include <sys/filedesc.h>
39 #include <sys/namei.h>
40 #include <sys/imgact.h>
41 #include <sys/kernel.h>
42 #include <sys/limits.h>
43 #include <sys/lock.h>
44 #include <sys/malloc.h>
45 #include <sys/file.h>		/* Must come after sys/malloc.h */
46 #include <sys/mbuf.h>
47 #include <sys/mman.h>
48 #include <sys/module.h>
49 #include <sys/mount.h>
50 #include <sys/mutex.h>
51 #include <sys/namei.h>
52 #include <sys/param.h>
53 #include <sys/proc.h>
54 #include <sys/reboot.h>
55 #include <sys/resource.h>
56 #include <sys/resourcevar.h>
57 #include <sys/selinfo.h>
58 #include <sys/eventvar.h>	/* Must come after sys/selinfo.h */
59 #include <sys/pipe.h>		/* Must come after sys/selinfo.h */
60 #include <sys/signal.h>
61 #include <sys/signalvar.h>
62 #include <sys/socket.h>
63 #include <sys/socketvar.h>
64 #include <sys/stat.h>
65 #include <sys/syscall.h>
66 #include <sys/syscallsubr.h>
67 #include <sys/sysctl.h>
68 #include <sys/sysent.h>
69 #include <sys/sysproto.h>
70 #include <sys/systm.h>
71 #include <sys/thr.h>
72 #include <sys/unistd.h>
73 #include <sys/ucontext.h>
74 #include <sys/vnode.h>
75 #include <sys/wait.h>
76 #include <sys/ipc.h>
77 #include <sys/shm.h>
78 
79 #include <vm/vm.h>
80 #include <vm/vm_kern.h>
81 #include <vm/vm_param.h>
82 #include <vm/pmap.h>
83 #include <vm/vm_map.h>
84 #include <vm/vm_object.h>
85 #include <vm/vm_extern.h>
86 
87 #include <machine/cpu.h>
88 
89 #include <compat/freebsd32/freebsd32_util.h>
90 #include <compat/freebsd32/freebsd32.h>
91 #include <compat/freebsd32/freebsd32_signal.h>
92 #include <compat/freebsd32/freebsd32_proto.h>
93 
94 CTASSERT(sizeof(struct timeval32) == 8);
95 CTASSERT(sizeof(struct timespec32) == 8);
96 CTASSERT(sizeof(struct statfs32) == 256);
97 CTASSERT(sizeof(struct rusage32) == 72);
98 
99 int
100 freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
101 {
102 	int error, status;
103 	struct rusage32 ru32;
104 	struct rusage ru, *rup;
105 
106 	if (uap->rusage != NULL)
107 		rup = &ru;
108 	else
109 		rup = NULL;
110 	error = kern_wait(td, uap->pid, &status, uap->options, rup);
111 	if (error)
112 		return (error);
113 	if (uap->status != NULL)
114 		error = copyout(&status, uap->status, sizeof(status));
115 	if (uap->rusage != NULL && error == 0) {
116 		TV_CP(ru, ru32, ru_utime);
117 		TV_CP(ru, ru32, ru_stime);
118 		CP(ru, ru32, ru_maxrss);
119 		CP(ru, ru32, ru_ixrss);
120 		CP(ru, ru32, ru_idrss);
121 		CP(ru, ru32, ru_isrss);
122 		CP(ru, ru32, ru_minflt);
123 		CP(ru, ru32, ru_majflt);
124 		CP(ru, ru32, ru_nswap);
125 		CP(ru, ru32, ru_inblock);
126 		CP(ru, ru32, ru_oublock);
127 		CP(ru, ru32, ru_msgsnd);
128 		CP(ru, ru32, ru_msgrcv);
129 		CP(ru, ru32, ru_nsignals);
130 		CP(ru, ru32, ru_nvcsw);
131 		CP(ru, ru32, ru_nivcsw);
132 		error = copyout(&ru32, uap->rusage, sizeof(ru32));
133 	}
134 	return (error);
135 }
136 
137 #ifdef COMPAT_FREEBSD4
138 static void
139 copy_statfs(struct statfs *in, struct statfs32 *out)
140 {
141 
142 	bzero(out, sizeof(*out));
143 	CP(*in, *out, f_bsize);
144 	CP(*in, *out, f_iosize);
145 	CP(*in, *out, f_blocks);
146 	CP(*in, *out, f_bfree);
147 	CP(*in, *out, f_bavail);
148 	CP(*in, *out, f_files);
149 	CP(*in, *out, f_ffree);
150 	CP(*in, *out, f_fsid);
151 	CP(*in, *out, f_owner);
152 	CP(*in, *out, f_type);
153 	CP(*in, *out, f_flags);
154 	CP(*in, *out, f_flags);
155 	CP(*in, *out, f_syncwrites);
156 	CP(*in, *out, f_asyncwrites);
157 	strlcpy(out->f_fstypename,
158 	      in->f_fstypename, MFSNAMELEN);
159 	strlcpy(out->f_mntonname,
160 	      in->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN));
161 	CP(*in, *out, f_syncreads);
162 	CP(*in, *out, f_asyncreads);
163 	strlcpy(out->f_mntfromname,
164 	      in->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN));
165 }
166 #endif
167 
168 #ifdef COMPAT_FREEBSD4
169 int
170 freebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap)
171 {
172 	struct statfs *buf, *sp;
173 	struct statfs32 stat32;
174 	size_t count, size;
175 	int error;
176 
177 	count = uap->bufsize / sizeof(struct statfs32);
178 	size = count * sizeof(struct statfs);
179 	error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags);
180 	if (size > 0) {
181 		count = td->td_retval[0];
182 		sp = buf;
183 		while (count > 0 && error == 0) {
184 			copy_statfs(sp, &stat32);
185 			error = copyout(&stat32, uap->buf, sizeof(stat32));
186 			sp++;
187 			uap->buf++;
188 			count--;
189 		}
190 		free(buf, M_TEMP);
191 	}
192 	return (error);
193 }
194 #endif
195 
196 CTASSERT(sizeof(struct sigaltstack32) == 12);
197 
198 int
199 freebsd32_sigaltstack(struct thread *td,
200 		      struct freebsd32_sigaltstack_args *uap)
201 {
202 	struct sigaltstack32 s32;
203 	struct sigaltstack ss, oss, *ssp;
204 	int error;
205 
206 	if (uap->ss != NULL) {
207 		error = copyin(uap->ss, &s32, sizeof(s32));
208 		if (error)
209 			return (error);
210 		PTRIN_CP(s32, ss, ss_sp);
211 		CP(s32, ss, ss_size);
212 		CP(s32, ss, ss_flags);
213 		ssp = &ss;
214 	} else
215 		ssp = NULL;
216 	error = kern_sigaltstack(td, ssp, &oss);
217 	if (error == 0 && uap->oss != NULL) {
218 		PTROUT_CP(oss, s32, ss_sp);
219 		CP(oss, s32, ss_size);
220 		CP(oss, s32, ss_flags);
221 		error = copyout(&s32, uap->oss, sizeof(s32));
222 	}
223 	return (error);
224 }
225 
226 /*
227  * Custom version of exec_copyin_args() so that we can translate
228  * the pointers.
229  */
230 static int
231 freebsd32_exec_copyin_args(struct image_args *args, char *fname,
232     enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv)
233 {
234 	char *argp, *envp;
235 	u_int32_t *p32, arg;
236 	size_t length;
237 	int error;
238 
239 	bzero(args, sizeof(*args));
240 	if (argv == NULL)
241 		return (EFAULT);
242 
243 	/*
244 	 * Allocate temporary demand zeroed space for argument and
245 	 *	environment strings
246 	 */
247 	args->buf = (char *) kmem_alloc_wait(exec_map,
248 	    PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
249 	if (args->buf == NULL)
250 		return (ENOMEM);
251 	args->begin_argv = args->buf;
252 	args->endp = args->begin_argv;
253 	args->stringspace = ARG_MAX;
254 
255 	args->fname = args->buf + ARG_MAX;
256 
257 	/*
258 	 * Copy the file name.
259 	 */
260 	error = (segflg == UIO_SYSSPACE) ?
261 	    copystr(fname, args->fname, PATH_MAX, &length) :
262 	    copyinstr(fname, args->fname, PATH_MAX, &length);
263 	if (error != 0)
264 		goto err_exit;
265 
266 	/*
267 	 * extract arguments first
268 	 */
269 	p32 = argv;
270 	for (;;) {
271 		error = copyin(p32++, &arg, sizeof(arg));
272 		if (error)
273 			goto err_exit;
274 		if (arg == 0)
275 			break;
276 		argp = PTRIN(arg);
277 		error = copyinstr(argp, args->endp, args->stringspace, &length);
278 		if (error) {
279 			if (error == ENAMETOOLONG)
280 				error = E2BIG;
281 			goto err_exit;
282 		}
283 		args->stringspace -= length;
284 		args->endp += length;
285 		args->argc++;
286 	}
287 
288 	args->begin_envv = args->endp;
289 
290 	/*
291 	 * extract environment strings
292 	 */
293 	if (envv) {
294 		p32 = envv;
295 		for (;;) {
296 			error = copyin(p32++, &arg, sizeof(arg));
297 			if (error)
298 				goto err_exit;
299 			if (arg == 0)
300 				break;
301 			envp = PTRIN(arg);
302 			error = copyinstr(envp, args->endp, args->stringspace,
303 			    &length);
304 			if (error) {
305 				if (error == ENAMETOOLONG)
306 					error = E2BIG;
307 				goto err_exit;
308 			}
309 			args->stringspace -= length;
310 			args->endp += length;
311 			args->envc++;
312 		}
313 	}
314 
315 	return (0);
316 
317 err_exit:
318 	kmem_free_wakeup(exec_map, (vm_offset_t)args->buf,
319 	    PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
320 	args->buf = NULL;
321 	return (error);
322 }
323 
324 int
325 freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
326 {
327 	struct image_args eargs;
328 	int error;
329 
330 	error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE,
331 	    uap->argv, uap->envv);
332 	if (error == 0)
333 		error = kern_execve(td, &eargs, NULL);
334 	return (error);
335 }
336 
337 #ifdef __ia64__
338 static int
339 freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
340 		       int prot, int fd, off_t pos)
341 {
342 	vm_map_t map;
343 	vm_map_entry_t entry;
344 	int rv;
345 
346 	map = &td->td_proc->p_vmspace->vm_map;
347 	if (fd != -1)
348 		prot |= VM_PROT_WRITE;
349 
350 	if (vm_map_lookup_entry(map, start, &entry)) {
351 		if ((entry->protection & prot) != prot) {
352 			rv = vm_map_protect(map,
353 					    trunc_page(start),
354 					    round_page(end),
355 					    entry->protection | prot,
356 					    FALSE);
357 			if (rv != KERN_SUCCESS)
358 				return (EINVAL);
359 		}
360 	} else {
361 		vm_offset_t addr = trunc_page(start);
362 		rv = vm_map_find(map, 0, 0,
363 				 &addr, PAGE_SIZE, FALSE, prot,
364 				 VM_PROT_ALL, 0);
365 		if (rv != KERN_SUCCESS)
366 			return (EINVAL);
367 	}
368 
369 	if (fd != -1) {
370 		struct pread_args r;
371 		r.fd = fd;
372 		r.buf = (void *) start;
373 		r.nbyte = end - start;
374 		r.offset = pos;
375 		return (pread(td, &r));
376 	} else {
377 		while (start < end) {
378 			subyte((void *) start, 0);
379 			start++;
380 		}
381 		return (0);
382 	}
383 }
384 #endif
385 
386 int
387 freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
388 {
389 	struct mmap_args ap;
390 	vm_offset_t addr = (vm_offset_t) uap->addr;
391 	vm_size_t len	 = uap->len;
392 	int prot	 = uap->prot;
393 	int flags	 = uap->flags;
394 	int fd		 = uap->fd;
395 	off_t pos	 = (uap->poslo
396 			    | ((off_t)uap->poshi << 32));
397 #ifdef __ia64__
398 	vm_size_t pageoff;
399 	int error;
400 
401 	/*
402 	 * Attempt to handle page size hassles.
403 	 */
404 	pageoff = (pos & PAGE_MASK);
405 	if (flags & MAP_FIXED) {
406 		vm_offset_t start, end;
407 		start = addr;
408 		end = addr + len;
409 
410 		mtx_lock(&Giant);
411 		if (start != trunc_page(start)) {
412 			error = freebsd32_mmap_partial(td, start,
413 						       round_page(start), prot,
414 						       fd, pos);
415 			if (fd != -1)
416 				pos += round_page(start) - start;
417 			start = round_page(start);
418 		}
419 		if (end != round_page(end)) {
420 			vm_offset_t t = trunc_page(end);
421 			error = freebsd32_mmap_partial(td, t, end,
422 						  prot, fd,
423 						  pos + t - start);
424 			end = trunc_page(end);
425 		}
426 		if (end > start && fd != -1 && (pos & PAGE_MASK)) {
427 			/*
428 			 * We can't map this region at all. The specified
429 			 * address doesn't have the same alignment as the file
430 			 * position. Fake the mapping by simply reading the
431 			 * entire region into memory. First we need to make
432 			 * sure the region exists.
433 			 */
434 			vm_map_t map;
435 			struct pread_args r;
436 			int rv;
437 
438 			prot |= VM_PROT_WRITE;
439 			map = &td->td_proc->p_vmspace->vm_map;
440 			rv = vm_map_remove(map, start, end);
441 			if (rv != KERN_SUCCESS) {
442 				mtx_unlock(&Giant);
443 				return (EINVAL);
444 			}
445 			rv = vm_map_find(map, 0, 0,
446 					 &start, end - start, FALSE,
447 					 prot, VM_PROT_ALL, 0);
448 			mtx_unlock(&Giant);
449 			if (rv != KERN_SUCCESS)
450 				return (EINVAL);
451 			r.fd = fd;
452 			r.buf = (void *) start;
453 			r.nbyte = end - start;
454 			r.offset = pos;
455 			error = pread(td, &r);
456 			if (error)
457 				return (error);
458 
459 			td->td_retval[0] = addr;
460 			return (0);
461 		}
462 		mtx_unlock(&Giant);
463 		if (end == start) {
464 			/*
465 			 * After dealing with the ragged ends, there
466 			 * might be none left.
467 			 */
468 			td->td_retval[0] = addr;
469 			return (0);
470 		}
471 		addr = start;
472 		len = end - start;
473 	}
474 #endif
475 
476 	ap.addr = (void *) addr;
477 	ap.len = len;
478 	ap.prot = prot;
479 	ap.flags = flags;
480 	ap.fd = fd;
481 	ap.pos = pos;
482 
483 	return (mmap(td, &ap));
484 }
485 
486 struct itimerval32 {
487 	struct timeval32 it_interval;
488 	struct timeval32 it_value;
489 };
490 
491 CTASSERT(sizeof(struct itimerval32) == 16);
492 
493 int
494 freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
495 {
496 	struct itimerval itv, oitv, *itvp;
497 	struct itimerval32 i32;
498 	int error;
499 
500 	if (uap->itv != NULL) {
501 		error = copyin(uap->itv, &i32, sizeof(i32));
502 		if (error)
503 			return (error);
504 		TV_CP(i32, itv, it_interval);
505 		TV_CP(i32, itv, it_value);
506 		itvp = &itv;
507 	} else
508 		itvp = NULL;
509 	error = kern_setitimer(td, uap->which, itvp, &oitv);
510 	if (error || uap->oitv == NULL)
511 		return (error);
512 	TV_CP(oitv, i32, it_interval);
513 	TV_CP(oitv, i32, it_value);
514 	return (copyout(&i32, uap->oitv, sizeof(i32)));
515 }
516 
517 int
518 freebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)
519 {
520 	struct itimerval itv;
521 	struct itimerval32 i32;
522 	int error;
523 
524 	error = kern_getitimer(td, uap->which, &itv);
525 	if (error || uap->itv == NULL)
526 		return (error);
527 	TV_CP(itv, i32, it_interval);
528 	TV_CP(itv, i32, it_value);
529 	return (copyout(&i32, uap->itv, sizeof(i32)));
530 }
531 
532 int
533 freebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
534 {
535 	struct timeval32 tv32;
536 	struct timeval tv, *tvp;
537 	int error;
538 
539 	if (uap->tv != NULL) {
540 		error = copyin(uap->tv, &tv32, sizeof(tv32));
541 		if (error)
542 			return (error);
543 		CP(tv32, tv, tv_sec);
544 		CP(tv32, tv, tv_usec);
545 		tvp = &tv;
546 	} else
547 		tvp = NULL;
548 	/*
549 	 * XXX big-endian needs to convert the fd_sets too.
550 	 * XXX Do pointers need PTRIN()?
551 	 */
552 	return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp));
553 }
554 
555 struct kevent32 {
556 	u_int32_t	ident;		/* identifier for this event */
557 	short		filter;		/* filter for event */
558 	u_short		flags;
559 	u_int		fflags;
560 	int32_t		data;
561 	u_int32_t	udata;		/* opaque user data identifier */
562 };
563 
564 CTASSERT(sizeof(struct kevent32) == 20);
565 static int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);
566 static int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count);
567 
568 /*
569  * Copy 'count' items into the destination list pointed to by uap->eventlist.
570  */
571 static int
572 freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count)
573 {
574 	struct freebsd32_kevent_args *uap;
575 	struct kevent32	ks32[KQ_NEVENTS];
576 	int i, error = 0;
577 
578 	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
579 	uap = (struct freebsd32_kevent_args *)arg;
580 
581 	for (i = 0; i < count; i++) {
582 		CP(kevp[i], ks32[i], ident);
583 		CP(kevp[i], ks32[i], filter);
584 		CP(kevp[i], ks32[i], flags);
585 		CP(kevp[i], ks32[i], fflags);
586 		CP(kevp[i], ks32[i], data);
587 		PTROUT_CP(kevp[i], ks32[i], udata);
588 	}
589 	error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
590 	if (error == 0)
591 		uap->eventlist += count;
592 	return (error);
593 }
594 
595 /*
596  * Copy 'count' items from the list pointed to by uap->changelist.
597  */
598 static int
599 freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)
600 {
601 	struct freebsd32_kevent_args *uap;
602 	struct kevent32	ks32[KQ_NEVENTS];
603 	int i, error = 0;
604 
605 	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
606 	uap = (struct freebsd32_kevent_args *)arg;
607 
608 	error = copyin(uap->changelist, ks32, count * sizeof *ks32);
609 	if (error)
610 		goto done;
611 	uap->changelist += count;
612 
613 	for (i = 0; i < count; i++) {
614 		CP(ks32[i], kevp[i], ident);
615 		CP(ks32[i], kevp[i], filter);
616 		CP(ks32[i], kevp[i], flags);
617 		CP(ks32[i], kevp[i], fflags);
618 		CP(ks32[i], kevp[i], data);
619 		PTRIN_CP(ks32[i], kevp[i], udata);
620 	}
621 done:
622 	return (error);
623 }
624 
625 int
626 freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
627 {
628 	struct timespec32 ts32;
629 	struct timespec ts, *tsp;
630 	struct kevent_copyops k_ops = { uap,
631 					freebsd32_kevent_copyout,
632 					freebsd32_kevent_copyin};
633 	int error;
634 
635 
636 	if (uap->timeout) {
637 		error = copyin(uap->timeout, &ts32, sizeof(ts32));
638 		if (error)
639 			return (error);
640 		CP(ts32, ts, tv_sec);
641 		CP(ts32, ts, tv_nsec);
642 		tsp = &ts;
643 	} else
644 		tsp = NULL;
645 	error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,
646 	    &k_ops, tsp);
647 	return (error);
648 }
649 
650 int
651 freebsd32_gettimeofday(struct thread *td,
652 		       struct freebsd32_gettimeofday_args *uap)
653 {
654 	struct timeval atv;
655 	struct timeval32 atv32;
656 	struct timezone rtz;
657 	int error = 0;
658 
659 	if (uap->tp) {
660 		microtime(&atv);
661 		CP(atv, atv32, tv_sec);
662 		CP(atv, atv32, tv_usec);
663 		error = copyout(&atv32, uap->tp, sizeof (atv32));
664 	}
665 	if (error == 0 && uap->tzp != NULL) {
666 		rtz.tz_minuteswest = tz_minuteswest;
667 		rtz.tz_dsttime = tz_dsttime;
668 		error = copyout(&rtz, uap->tzp, sizeof (rtz));
669 	}
670 	return (error);
671 }
672 
673 int
674 freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
675 {
676 	struct rusage32 s32;
677 	struct rusage s;
678 	int error;
679 
680 	error = kern_getrusage(td, uap->who, &s);
681 	if (error)
682 		return (error);
683 	if (uap->rusage != NULL) {
684 		TV_CP(s, s32, ru_utime);
685 		TV_CP(s, s32, ru_stime);
686 		CP(s, s32, ru_maxrss);
687 		CP(s, s32, ru_ixrss);
688 		CP(s, s32, ru_idrss);
689 		CP(s, s32, ru_isrss);
690 		CP(s, s32, ru_minflt);
691 		CP(s, s32, ru_majflt);
692 		CP(s, s32, ru_nswap);
693 		CP(s, s32, ru_inblock);
694 		CP(s, s32, ru_oublock);
695 		CP(s, s32, ru_msgsnd);
696 		CP(s, s32, ru_msgrcv);
697 		CP(s, s32, ru_nsignals);
698 		CP(s, s32, ru_nvcsw);
699 		CP(s, s32, ru_nivcsw);
700 		error = copyout(&s32, uap->rusage, sizeof(s32));
701 	}
702 	return (error);
703 }
704 
705 struct iovec32 {
706 	u_int32_t iov_base;
707 	int	iov_len;
708 };
709 
710 CTASSERT(sizeof(struct iovec32) == 8);
711 
712 static int
713 freebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
714 {
715 	struct iovec32 iov32;
716 	struct iovec *iov;
717 	struct uio *uio;
718 	u_int iovlen;
719 	int error, i;
720 
721 	*uiop = NULL;
722 	if (iovcnt > UIO_MAXIOV)
723 		return (EINVAL);
724 	iovlen = iovcnt * sizeof(struct iovec);
725 	uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
726 	iov = (struct iovec *)(uio + 1);
727 	for (i = 0; i < iovcnt; i++) {
728 		error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
729 		if (error) {
730 			free(uio, M_IOV);
731 			return (error);
732 		}
733 		iov[i].iov_base = PTRIN(iov32.iov_base);
734 		iov[i].iov_len = iov32.iov_len;
735 	}
736 	uio->uio_iov = iov;
737 	uio->uio_iovcnt = iovcnt;
738 	uio->uio_segflg = UIO_USERSPACE;
739 	uio->uio_offset = -1;
740 	uio->uio_resid = 0;
741 	for (i = 0; i < iovcnt; i++) {
742 		if (iov->iov_len > INT_MAX - uio->uio_resid) {
743 			free(uio, M_IOV);
744 			return (EINVAL);
745 		}
746 		uio->uio_resid += iov->iov_len;
747 		iov++;
748 	}
749 	*uiop = uio;
750 	return (0);
751 }
752 
753 int
754 freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
755 {
756 	struct uio *auio;
757 	int error;
758 
759 	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
760 	if (error)
761 		return (error);
762 	error = kern_readv(td, uap->fd, auio);
763 	free(auio, M_IOV);
764 	return (error);
765 }
766 
767 int
768 freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
769 {
770 	struct uio *auio;
771 	int error;
772 
773 	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
774 	if (error)
775 		return (error);
776 	error = kern_writev(td, uap->fd, auio);
777 	free(auio, M_IOV);
778 	return (error);
779 }
780 
781 int
782 freebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap)
783 {
784 	struct uio *auio;
785 	int error;
786 
787 	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
788 	if (error)
789 		return (error);
790 	error = kern_preadv(td, uap->fd, auio, uap->offset);
791 	free(auio, M_IOV);
792 	return (error);
793 }
794 
795 int
796 freebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap)
797 {
798 	struct uio *auio;
799 	int error;
800 
801 	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
802 	if (error)
803 		return (error);
804 	error = kern_pwritev(td, uap->fd, auio, uap->offset);
805 	free(auio, M_IOV);
806 	return (error);
807 }
808 
809 static int
810 freebsd32_copyiniov(struct iovec32 *iovp32, u_int iovcnt, struct iovec **iovp,
811     int error)
812 {
813 	struct iovec32 iov32;
814 	struct iovec *iov;
815 	u_int iovlen;
816 	int i;
817 
818 	*iovp = NULL;
819 	if (iovcnt > UIO_MAXIOV)
820 		return (error);
821 	iovlen = iovcnt * sizeof(struct iovec);
822 	iov = malloc(iovlen, M_IOV, M_WAITOK);
823 	for (i = 0; i < iovcnt; i++) {
824 		error = copyin(&iovp32[i], &iov32, sizeof(struct iovec32));
825 		if (error) {
826 			free(iov, M_IOV);
827 			return (error);
828 		}
829 		iov[i].iov_base = PTRIN(iov32.iov_base);
830 		iov[i].iov_len = iov32.iov_len;
831 	}
832 	*iovp = iov;
833 	return (0);
834 }
835 
836 struct msghdr32 {
837 	u_int32_t	 msg_name;
838 	socklen_t	 msg_namelen;
839 	u_int32_t	 msg_iov;
840 	int		 msg_iovlen;
841 	u_int32_t	 msg_control;
842 	socklen_t	 msg_controllen;
843 	int		 msg_flags;
844 };
845 CTASSERT(sizeof(struct msghdr32) == 28);
846 
847 static int
848 freebsd32_copyinmsghdr(struct msghdr32 *msg32, struct msghdr *msg)
849 {
850 	struct msghdr32 m32;
851 	int error;
852 
853 	error = copyin(msg32, &m32, sizeof(m32));
854 	if (error)
855 		return (error);
856 	msg->msg_name = PTRIN(m32.msg_name);
857 	msg->msg_namelen = m32.msg_namelen;
858 	msg->msg_iov = PTRIN(m32.msg_iov);
859 	msg->msg_iovlen = m32.msg_iovlen;
860 	msg->msg_control = PTRIN(m32.msg_control);
861 	msg->msg_controllen = m32.msg_controllen;
862 	msg->msg_flags = m32.msg_flags;
863 	return (0);
864 }
865 
866 static int
867 freebsd32_copyoutmsghdr(struct msghdr *msg, struct msghdr32 *msg32)
868 {
869 	struct msghdr32 m32;
870 	int error;
871 
872 	m32.msg_name = PTROUT(msg->msg_name);
873 	m32.msg_namelen = msg->msg_namelen;
874 	m32.msg_iov = PTROUT(msg->msg_iov);
875 	m32.msg_iovlen = msg->msg_iovlen;
876 	m32.msg_control = PTROUT(msg->msg_control);
877 	m32.msg_controllen = msg->msg_controllen;
878 	m32.msg_flags = msg->msg_flags;
879 	error = copyout(&m32, msg32, sizeof(m32));
880 	return (error);
881 }
882 
883 #define FREEBSD32_ALIGNBYTES	(sizeof(int) - 1)
884 #define FREEBSD32_ALIGN(p)	\
885 	(((u_long)(p) + FREEBSD32_ALIGNBYTES) & ~FREEBSD32_ALIGNBYTES)
886 #define	FREEBSD32_CMSG_SPACE(l)	\
887 	(FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + FREEBSD32_ALIGN(l))
888 
889 #define	FREEBSD32_CMSG_DATA(cmsg)	((unsigned char *)(cmsg) + \
890 				 FREEBSD32_ALIGN(sizeof(struct cmsghdr)))
891 static int
892 freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf *control)
893 {
894 	struct cmsghdr *cm;
895 	void *data;
896 	socklen_t clen, datalen;
897 	int error;
898 	caddr_t ctlbuf;
899 	int len, maxlen, copylen;
900 	struct mbuf *m;
901 	error = 0;
902 
903 	len    = msg->msg_controllen;
904 	maxlen = msg->msg_controllen;
905 	msg->msg_controllen = 0;
906 
907 	m = control;
908 	ctlbuf = msg->msg_control;
909 
910 	while (m && len > 0) {
911 		cm = mtod(m, struct cmsghdr *);
912 		clen = m->m_len;
913 
914 		while (cm != NULL) {
915 
916 			if (sizeof(struct cmsghdr) > clen ||
917 			    cm->cmsg_len > clen) {
918 				error = EINVAL;
919 				break;
920 			}
921 
922 			data   = CMSG_DATA(cm);
923 			datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
924 
925 			/* Adjust message length */
926 			cm->cmsg_len = FREEBSD32_ALIGN(sizeof(struct cmsghdr)) +
927 			    datalen;
928 
929 
930 			/* Copy cmsghdr */
931 			copylen = sizeof(struct cmsghdr);
932 			if (len < copylen) {
933 				msg->msg_flags |= MSG_CTRUNC;
934 				copylen = len;
935 			}
936 
937 			error = copyout(cm,ctlbuf,copylen);
938 			if (error)
939 				goto exit;
940 
941 			ctlbuf += FREEBSD32_ALIGN(copylen);
942 			len    -= FREEBSD32_ALIGN(copylen);
943 
944 			if (len <= 0)
945 				break;
946 
947 			/* Copy data */
948 			copylen = datalen;
949 			if (len < copylen) {
950 				msg->msg_flags |= MSG_CTRUNC;
951 				copylen = len;
952 			}
953 
954 			error = copyout(data,ctlbuf,copylen);
955 			if (error)
956 				goto exit;
957 
958 			ctlbuf += FREEBSD32_ALIGN(copylen);
959 			len    -= FREEBSD32_ALIGN(copylen);
960 
961 			if (CMSG_SPACE(datalen) < clen) {
962 				clen -= CMSG_SPACE(datalen);
963 				cm = (struct cmsghdr *)
964 					((caddr_t)cm + CMSG_SPACE(datalen));
965 			} else {
966 				clen = 0;
967 				cm = NULL;
968 			}
969 		}
970 		m = m->m_next;
971 	}
972 
973 	msg->msg_controllen = (len <= 0) ? maxlen :  ctlbuf - (caddr_t)msg->msg_control;
974 
975 exit:
976 	return (error);
977 
978 }
979 
980 int
981 freebsd32_recvmsg(td, uap)
982 	struct thread *td;
983 	struct freebsd32_recvmsg_args /* {
984 		int	s;
985 		struct	msghdr32 *msg;
986 		int	flags;
987 	} */ *uap;
988 {
989 	struct msghdr msg;
990 	struct msghdr32 m32;
991 	struct iovec *uiov, *iov;
992 	struct mbuf *control = NULL;
993 	struct mbuf **controlp;
994 
995 	int error;
996 	error = copyin(uap->msg, &m32, sizeof(m32));
997 	if (error)
998 		return (error);
999 	error = freebsd32_copyinmsghdr(uap->msg, &msg);
1000 	if (error)
1001 		return (error);
1002 	error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov,
1003 	    EMSGSIZE);
1004 	if (error)
1005 		return (error);
1006 	msg.msg_flags = uap->flags;
1007 	uiov = msg.msg_iov;
1008 	msg.msg_iov = iov;
1009 
1010 	controlp = (msg.msg_control != NULL) ?  &control : NULL;
1011 	error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, controlp);
1012 	if (error == 0) {
1013 		msg.msg_iov = uiov;
1014 
1015 		if (control != NULL)
1016 			error = freebsd32_copy_msg_out(&msg, control);
1017 
1018 		if (error == 0)
1019 			error = freebsd32_copyoutmsghdr(&msg, uap->msg);
1020 	}
1021 	free(iov, M_IOV);
1022 
1023 	if (control != NULL)
1024 		m_freem(control);
1025 
1026 	return (error);
1027 }
1028 
1029 
1030 static int
1031 freebsd32_convert_msg_in(struct mbuf **controlp)
1032 {
1033 	struct mbuf *control = *controlp;
1034 	struct cmsghdr *cm = mtod(control, struct cmsghdr *);
1035 	void *data;
1036 	socklen_t clen = control->m_len, datalen;
1037 	int error;
1038 
1039 	error = 0;
1040 	*controlp = NULL;
1041 
1042 	while (cm != NULL) {
1043 		if (sizeof(struct cmsghdr) > clen || cm->cmsg_len > clen) {
1044 			error = EINVAL;
1045 			break;
1046 		}
1047 
1048 		data = FREEBSD32_CMSG_DATA(cm);
1049 		datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
1050 
1051 		*controlp = sbcreatecontrol(data, datalen, cm->cmsg_type,
1052 		    cm->cmsg_level);
1053 		controlp = &(*controlp)->m_next;
1054 
1055 		if (FREEBSD32_CMSG_SPACE(datalen) < clen) {
1056 			clen -= FREEBSD32_CMSG_SPACE(datalen);
1057 			cm = (struct cmsghdr *)
1058 				((caddr_t)cm + FREEBSD32_CMSG_SPACE(datalen));
1059 		} else {
1060 			clen = 0;
1061 			cm = NULL;
1062 		}
1063 	}
1064 
1065 	m_freem(control);
1066 	return (error);
1067 }
1068 
1069 
1070 int
1071 freebsd32_sendmsg(struct thread *td,
1072 		  struct freebsd32_sendmsg_args *uap)
1073 {
1074 	struct msghdr msg;
1075 	struct msghdr32 m32;
1076 	struct iovec *iov;
1077 	struct mbuf *control = NULL;
1078 	struct sockaddr *to = NULL;
1079 	int error;
1080 
1081 	error = copyin(uap->msg, &m32, sizeof(m32));
1082 	if (error)
1083 		return (error);
1084 	error = freebsd32_copyinmsghdr(uap->msg, &msg);
1085 	if (error)
1086 		return (error);
1087 	error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov,
1088 	    EMSGSIZE);
1089 	if (error)
1090 		return (error);
1091 	msg.msg_iov = iov;
1092 	if (msg.msg_name != NULL) {
1093 		error = getsockaddr(&to, msg.msg_name, msg.msg_namelen);
1094 		if (error) {
1095 			to = NULL;
1096 			goto out;
1097 		}
1098 		msg.msg_name = to;
1099 	}
1100 
1101 	if (msg.msg_control) {
1102 		if (msg.msg_controllen < sizeof(struct cmsghdr)) {
1103 			error = EINVAL;
1104 			goto out;
1105 		}
1106 
1107 		error = sockargs(&control, msg.msg_control,
1108 		    msg.msg_controllen, MT_CONTROL);
1109 		if (error)
1110 			goto out;
1111 
1112 		error = freebsd32_convert_msg_in(&control);
1113 		if (error)
1114 			goto out;
1115 	}
1116 
1117 	error = kern_sendit(td, uap->s, &msg, uap->flags, control,
1118 	    UIO_USERSPACE);
1119 
1120 out:
1121 	free(iov, M_IOV);
1122 	if (to)
1123 		free(to, M_SONAME);
1124 	return (error);
1125 }
1126 
1127 int
1128 freebsd32_recvfrom(struct thread *td,
1129 		   struct freebsd32_recvfrom_args *uap)
1130 {
1131 	struct msghdr msg;
1132 	struct iovec aiov;
1133 	int error;
1134 
1135 	if (uap->fromlenaddr) {
1136 		error = copyin(PTRIN(uap->fromlenaddr), &msg.msg_namelen,
1137 		    sizeof(msg.msg_namelen));
1138 		if (error)
1139 			return (error);
1140 	} else {
1141 		msg.msg_namelen = 0;
1142 	}
1143 
1144 	msg.msg_name = PTRIN(uap->from);
1145 	msg.msg_iov = &aiov;
1146 	msg.msg_iovlen = 1;
1147 	aiov.iov_base = PTRIN(uap->buf);
1148 	aiov.iov_len = uap->len;
1149 	msg.msg_control = NULL;
1150 	msg.msg_flags = uap->flags;
1151 	error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, NULL);
1152 	if (error == 0 && uap->fromlenaddr)
1153 		error = copyout(&msg.msg_namelen, PTRIN(uap->fromlenaddr),
1154 		    sizeof (msg.msg_namelen));
1155 	return (error);
1156 }
1157 
1158 int
1159 freebsd32_settimeofday(struct thread *td,
1160 		       struct freebsd32_settimeofday_args *uap)
1161 {
1162 	struct timeval32 tv32;
1163 	struct timeval tv, *tvp;
1164 	struct timezone tz, *tzp;
1165 	int error;
1166 
1167 	if (uap->tv) {
1168 		error = copyin(uap->tv, &tv32, sizeof(tv32));
1169 		if (error)
1170 			return (error);
1171 		CP(tv32, tv, tv_sec);
1172 		CP(tv32, tv, tv_usec);
1173 		tvp = &tv;
1174 	} else
1175 		tvp = NULL;
1176 	if (uap->tzp) {
1177 		error = copyin(uap->tzp, &tz, sizeof(tz));
1178 		if (error)
1179 			return (error);
1180 		tzp = &tz;
1181 	} else
1182 		tzp = NULL;
1183 	return (kern_settimeofday(td, tvp, tzp));
1184 }
1185 
1186 int
1187 freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
1188 {
1189 	struct timeval32 s32[2];
1190 	struct timeval s[2], *sp;
1191 	int error;
1192 
1193 	if (uap->tptr != NULL) {
1194 		error = copyin(uap->tptr, s32, sizeof(s32));
1195 		if (error)
1196 			return (error);
1197 		CP(s32[0], s[0], tv_sec);
1198 		CP(s32[0], s[0], tv_usec);
1199 		CP(s32[1], s[1], tv_sec);
1200 		CP(s32[1], s[1], tv_usec);
1201 		sp = s;
1202 	} else
1203 		sp = NULL;
1204 	return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
1205 }
1206 
1207 int
1208 freebsd32_lutimes(struct thread *td, struct freebsd32_lutimes_args *uap)
1209 {
1210 	struct timeval32 s32[2];
1211 	struct timeval s[2], *sp;
1212 	int error;
1213 
1214 	if (uap->tptr != NULL) {
1215 		error = copyin(uap->tptr, s32, sizeof(s32));
1216 		if (error)
1217 			return (error);
1218 		CP(s32[0], s[0], tv_sec);
1219 		CP(s32[0], s[0], tv_usec);
1220 		CP(s32[1], s[1], tv_sec);
1221 		CP(s32[1], s[1], tv_usec);
1222 		sp = s;
1223 	} else
1224 		sp = NULL;
1225 	return (kern_lutimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
1226 }
1227 
1228 int
1229 freebsd32_futimes(struct thread *td, struct freebsd32_futimes_args *uap)
1230 {
1231 	struct timeval32 s32[2];
1232 	struct timeval s[2], *sp;
1233 	int error;
1234 
1235 	if (uap->tptr != NULL) {
1236 		error = copyin(uap->tptr, s32, sizeof(s32));
1237 		if (error)
1238 			return (error);
1239 		CP(s32[0], s[0], tv_sec);
1240 		CP(s32[0], s[0], tv_usec);
1241 		CP(s32[1], s[1], tv_sec);
1242 		CP(s32[1], s[1], tv_usec);
1243 		sp = s;
1244 	} else
1245 		sp = NULL;
1246 	return (kern_futimes(td, uap->fd, sp, UIO_SYSSPACE));
1247 }
1248 
1249 
1250 int
1251 freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
1252 {
1253 	struct timeval32 tv32;
1254 	struct timeval delta, olddelta, *deltap;
1255 	int error;
1256 
1257 	if (uap->delta) {
1258 		error = copyin(uap->delta, &tv32, sizeof(tv32));
1259 		if (error)
1260 			return (error);
1261 		CP(tv32, delta, tv_sec);
1262 		CP(tv32, delta, tv_usec);
1263 		deltap = &delta;
1264 	} else
1265 		deltap = NULL;
1266 	error = kern_adjtime(td, deltap, &olddelta);
1267 	if (uap->olddelta && error == 0) {
1268 		CP(olddelta, tv32, tv_sec);
1269 		CP(olddelta, tv32, tv_usec);
1270 		error = copyout(&tv32, uap->olddelta, sizeof(tv32));
1271 	}
1272 	return (error);
1273 }
1274 
1275 #ifdef COMPAT_FREEBSD4
1276 int
1277 freebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)
1278 {
1279 	struct statfs32 s32;
1280 	struct statfs s;
1281 	int error;
1282 
1283 	error = kern_statfs(td, uap->path, UIO_USERSPACE, &s);
1284 	if (error)
1285 		return (error);
1286 	copy_statfs(&s, &s32);
1287 	return (copyout(&s32, uap->buf, sizeof(s32)));
1288 }
1289 #endif
1290 
1291 #ifdef COMPAT_FREEBSD4
1292 int
1293 freebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)
1294 {
1295 	struct statfs32 s32;
1296 	struct statfs s;
1297 	int error;
1298 
1299 	error = kern_fstatfs(td, uap->fd, &s);
1300 	if (error)
1301 		return (error);
1302 	copy_statfs(&s, &s32);
1303 	return (copyout(&s32, uap->buf, sizeof(s32)));
1304 }
1305 #endif
1306 
1307 #ifdef COMPAT_FREEBSD4
1308 int
1309 freebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)
1310 {
1311 	struct statfs32 s32;
1312 	struct statfs s;
1313 	fhandle_t fh;
1314 	int error;
1315 
1316 	if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
1317 		return (error);
1318 	error = kern_fhstatfs(td, fh, &s);
1319 	if (error)
1320 		return (error);
1321 	copy_statfs(&s, &s32);
1322 	return (copyout(&s32, uap->buf, sizeof(s32)));
1323 }
1324 #endif
1325 
1326 int
1327 freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
1328 {
1329 	/*
1330 	 * Vector through to semsys if it is loaded.
1331 	 */
1332 	return sysent[SYS_semsys].sy_call(td, uap);
1333 }
1334 
1335 int
1336 freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
1337 {
1338 	switch (uap->which) {
1339 	case 2:
1340 		return (freebsd32_msgsnd(td,
1341 		    (struct freebsd32_msgsnd_args *)&uap->a2));
1342 		break;
1343 	case 3:
1344 		return (freebsd32_msgrcv(td,
1345 		    (struct freebsd32_msgrcv_args *)&uap->a2));
1346 		break;
1347 	default:
1348 		/*
1349 		 * Vector through to msgsys if it is loaded.
1350 		 */
1351 		return (sysent[SYS_msgsys].sy_call(td, uap));
1352 		break;
1353 	}
1354 }
1355 
1356 int
1357 freebsd32_msgsnd(struct thread *td, struct freebsd32_msgsnd_args *uap)
1358 {
1359 	const void *msgp;
1360 	long mtype;
1361 	int32_t mtype32;
1362 	int error;
1363 
1364 	if (!SYSCALL_MODULE_PRESENT(msgsnd))
1365 		return (nosys(td, (struct nosys_args *)uap));
1366 
1367 	msgp = PTRIN(uap->msgp);
1368 	if ((error = copyin(msgp, &mtype32, sizeof(mtype32))) != 0)
1369 		return (error);
1370 	mtype = mtype32;
1371 	return (kern_msgsnd(td, uap->msqid,
1372 	    (const char *)msgp + sizeof(mtype32),
1373 	    uap->msgsz, uap->msgflg, mtype));
1374 }
1375 
1376 int
1377 freebsd32_msgrcv(struct thread *td, struct freebsd32_msgrcv_args *uap)
1378 {
1379 	void *msgp;
1380 	long mtype;
1381 	int32_t mtype32;
1382 	int error;
1383 
1384 	if (!SYSCALL_MODULE_PRESENT(msgrcv))
1385 		return (nosys(td, (struct nosys_args *)uap));
1386 
1387 	msgp = PTRIN(uap->msgp);
1388 	if ((error = kern_msgrcv(td, uap->msqid,
1389 	    (char *)msgp + sizeof(mtype32), uap->msgsz,
1390 	    uap->msgtyp, uap->msgflg, &mtype)) != 0)
1391 		return (error);
1392 	mtype32 = (int32_t)mtype;
1393 	return (copyout(&mtype32, msgp, sizeof(mtype32)));
1394 }
1395 
1396 int
1397 freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
1398 {
1399 
1400 	switch (uap->which) {
1401 	case 0:	{	/* shmat */
1402 		struct shmat_args ap;
1403 
1404 		ap.shmid = uap->a2;
1405 		ap.shmaddr = PTRIN(uap->a3);
1406 		ap.shmflg = uap->a4;
1407 		return (sysent[SYS_shmat].sy_call(td, &ap));
1408 	}
1409 	case 2: {	/* shmdt */
1410 		struct shmdt_args ap;
1411 
1412 		ap.shmaddr = PTRIN(uap->a2);
1413 		return (sysent[SYS_shmdt].sy_call(td, &ap));
1414 	}
1415 	case 3: {	/* shmget */
1416 		struct shmget_args ap;
1417 
1418 		ap.key = uap->a2;
1419 		ap.size = uap->a3;
1420 		ap.shmflg = uap->a4;
1421 		return (sysent[SYS_shmget].sy_call(td, &ap));
1422 	}
1423 	case 4: {	/* shmctl */
1424 		struct freebsd32_shmctl_args ap;
1425 
1426 		ap.shmid = uap->a2;
1427 		ap.cmd = uap->a3;
1428 		ap.buf = PTRIN(uap->a4);
1429 		return (freebsd32_shmctl(td, &ap));
1430 	}
1431 	case 1:		/* oshmctl */
1432 	default:
1433 		return (EINVAL);
1434 	}
1435 }
1436 
1437 struct ipc_perm32 {
1438 	uint16_t	cuid;
1439 	uint16_t	cgid;
1440 	uint16_t	uid;
1441 	uint16_t	gid;
1442 	uint16_t	mode;
1443 	uint16_t	seq;
1444 	uint32_t	key;
1445 };
1446 struct shmid_ds32 {
1447 	struct ipc_perm32 shm_perm;
1448 	int32_t		shm_segsz;
1449 	int32_t		shm_lpid;
1450 	int32_t		shm_cpid;
1451 	int16_t		shm_nattch;
1452 	int32_t		shm_atime;
1453 	int32_t		shm_dtime;
1454 	int32_t		shm_ctime;
1455 	uint32_t	shm_internal;
1456 };
1457 struct shm_info32 {
1458 	int32_t		used_ids;
1459 	uint32_t	shm_tot;
1460 	uint32_t	shm_rss;
1461 	uint32_t	shm_swp;
1462 	uint32_t	swap_attempts;
1463 	uint32_t	swap_successes;
1464 };
1465 struct shminfo32 {
1466 	uint32_t	shmmax;
1467 	uint32_t	shmmin;
1468 	uint32_t	shmmni;
1469 	uint32_t	shmseg;
1470 	uint32_t	shmall;
1471 };
1472 
1473 int
1474 freebsd32_shmctl(struct thread *td, struct freebsd32_shmctl_args *uap)
1475 {
1476 	int error = 0;
1477 	union {
1478 		struct shmid_ds shmid_ds;
1479 		struct shm_info shm_info;
1480 		struct shminfo shminfo;
1481 	} u;
1482 	union {
1483 		struct shmid_ds32 shmid_ds32;
1484 		struct shm_info32 shm_info32;
1485 		struct shminfo32 shminfo32;
1486 	} u32;
1487 	size_t sz;
1488 
1489 	if (uap->cmd == IPC_SET) {
1490 		if ((error = copyin(uap->buf, &u32.shmid_ds32,
1491 		    sizeof(u32.shmid_ds32))))
1492 			goto done;
1493 		CP(u32.shmid_ds32, u.shmid_ds, shm_perm.cuid);
1494 		CP(u32.shmid_ds32, u.shmid_ds, shm_perm.cgid);
1495 		CP(u32.shmid_ds32, u.shmid_ds, shm_perm.uid);
1496 		CP(u32.shmid_ds32, u.shmid_ds, shm_perm.gid);
1497 		CP(u32.shmid_ds32, u.shmid_ds, shm_perm.mode);
1498 		CP(u32.shmid_ds32, u.shmid_ds, shm_perm.seq);
1499 		CP(u32.shmid_ds32, u.shmid_ds, shm_perm.key);
1500 		CP(u32.shmid_ds32, u.shmid_ds, shm_segsz);
1501 		CP(u32.shmid_ds32, u.shmid_ds, shm_lpid);
1502 		CP(u32.shmid_ds32, u.shmid_ds, shm_cpid);
1503 		CP(u32.shmid_ds32, u.shmid_ds, shm_nattch);
1504 		CP(u32.shmid_ds32, u.shmid_ds, shm_atime);
1505 		CP(u32.shmid_ds32, u.shmid_ds, shm_dtime);
1506 		CP(u32.shmid_ds32, u.shmid_ds, shm_ctime);
1507 		PTRIN_CP(u32.shmid_ds32, u.shmid_ds, shm_internal);
1508 	}
1509 
1510 	error = kern_shmctl(td, uap->shmid, uap->cmd, (void *)&u, &sz);
1511 	if (error)
1512 		goto done;
1513 
1514 	/* Cases in which we need to copyout */
1515 	switch (uap->cmd) {
1516 	case IPC_INFO:
1517 		CP(u.shminfo, u32.shminfo32, shmmax);
1518 		CP(u.shminfo, u32.shminfo32, shmmin);
1519 		CP(u.shminfo, u32.shminfo32, shmmni);
1520 		CP(u.shminfo, u32.shminfo32, shmseg);
1521 		CP(u.shminfo, u32.shminfo32, shmall);
1522 		error = copyout(&u32.shminfo32, uap->buf,
1523 		    sizeof(u32.shminfo32));
1524 		break;
1525 	case SHM_INFO:
1526 		CP(u.shm_info, u32.shm_info32, used_ids);
1527 		CP(u.shm_info, u32.shm_info32, shm_rss);
1528 		CP(u.shm_info, u32.shm_info32, shm_tot);
1529 		CP(u.shm_info, u32.shm_info32, shm_swp);
1530 		CP(u.shm_info, u32.shm_info32, swap_attempts);
1531 		CP(u.shm_info, u32.shm_info32, swap_successes);
1532 		error = copyout(&u32.shm_info32, uap->buf,
1533 		    sizeof(u32.shm_info32));
1534 		break;
1535 	case SHM_STAT:
1536 	case IPC_STAT:
1537 		CP(u.shmid_ds, u32.shmid_ds32, shm_perm.cuid);
1538 		CP(u.shmid_ds, u32.shmid_ds32, shm_perm.cgid);
1539 		CP(u.shmid_ds, u32.shmid_ds32, shm_perm.uid);
1540 		CP(u.shmid_ds, u32.shmid_ds32, shm_perm.gid);
1541 		CP(u.shmid_ds, u32.shmid_ds32, shm_perm.mode);
1542 		CP(u.shmid_ds, u32.shmid_ds32, shm_perm.seq);
1543 		CP(u.shmid_ds, u32.shmid_ds32, shm_perm.key);
1544 		CP(u.shmid_ds, u32.shmid_ds32, shm_segsz);
1545 		CP(u.shmid_ds, u32.shmid_ds32, shm_lpid);
1546 		CP(u.shmid_ds, u32.shmid_ds32, shm_cpid);
1547 		CP(u.shmid_ds, u32.shmid_ds32, shm_nattch);
1548 		CP(u.shmid_ds, u32.shmid_ds32, shm_atime);
1549 		CP(u.shmid_ds, u32.shmid_ds32, shm_dtime);
1550 		CP(u.shmid_ds, u32.shmid_ds32, shm_ctime);
1551 		PTROUT_CP(u.shmid_ds, u32.shmid_ds32, shm_internal);
1552 		error = copyout(&u32.shmid_ds32, uap->buf,
1553 		    sizeof(u32.shmid_ds32));
1554 		break;
1555 	}
1556 
1557 done:
1558 	if (error) {
1559 		/* Invalidate the return value */
1560 		td->td_retval[0] = -1;
1561 	}
1562 	return (error);
1563 }
1564 
1565 int
1566 freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
1567 {
1568 	struct pread_args ap;
1569 
1570 	ap.fd = uap->fd;
1571 	ap.buf = uap->buf;
1572 	ap.nbyte = uap->nbyte;
1573 	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1574 	return (pread(td, &ap));
1575 }
1576 
1577 int
1578 freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
1579 {
1580 	struct pwrite_args ap;
1581 
1582 	ap.fd = uap->fd;
1583 	ap.buf = uap->buf;
1584 	ap.nbyte = uap->nbyte;
1585 	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1586 	return (pwrite(td, &ap));
1587 }
1588 
1589 int
1590 freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
1591 {
1592 	int error;
1593 	struct lseek_args ap;
1594 	off_t pos;
1595 
1596 	ap.fd = uap->fd;
1597 	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1598 	ap.whence = uap->whence;
1599 	error = lseek(td, &ap);
1600 	/* Expand the quad return into two parts for eax and edx */
1601 	pos = *(off_t *)(td->td_retval);
1602 	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
1603 	td->td_retval[1] = pos >> 32;		/* %edx */
1604 	return error;
1605 }
1606 
1607 int
1608 freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
1609 {
1610 	struct truncate_args ap;
1611 
1612 	ap.path = uap->path;
1613 	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1614 	return (truncate(td, &ap));
1615 }
1616 
1617 int
1618 freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
1619 {
1620 	struct ftruncate_args ap;
1621 
1622 	ap.fd = uap->fd;
1623 	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1624 	return (ftruncate(td, &ap));
1625 }
1626 
1627 struct sf_hdtr32 {
1628 	uint32_t headers;
1629 	int hdr_cnt;
1630 	uint32_t trailers;
1631 	int trl_cnt;
1632 };
1633 
1634 static int
1635 freebsd32_do_sendfile(struct thread *td,
1636     struct freebsd32_sendfile_args *uap, int compat)
1637 {
1638 	struct sendfile_args ap;
1639 	struct sf_hdtr32 hdtr32;
1640 	struct sf_hdtr hdtr;
1641 	struct uio *hdr_uio, *trl_uio;
1642 	struct iovec32 *iov32;
1643 	int error;
1644 
1645 	hdr_uio = trl_uio = NULL;
1646 
1647 	ap.fd = uap->fd;
1648 	ap.s = uap->s;
1649 	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1650 	ap.nbytes = uap->nbytes;
1651 	ap.hdtr = (struct sf_hdtr *)uap->hdtr;		/* XXX not used */
1652 	ap.sbytes = uap->sbytes;
1653 	ap.flags = uap->flags;
1654 
1655 	if (uap->hdtr != NULL) {
1656 		error = copyin(uap->hdtr, &hdtr32, sizeof(hdtr32));
1657 		if (error)
1658 			goto out;
1659 		PTRIN_CP(hdtr32, hdtr, headers);
1660 		CP(hdtr32, hdtr, hdr_cnt);
1661 		PTRIN_CP(hdtr32, hdtr, trailers);
1662 		CP(hdtr32, hdtr, trl_cnt);
1663 
1664 		if (hdtr.headers != NULL) {
1665 			iov32 = PTRIN(hdtr32.headers);
1666 			error = freebsd32_copyinuio(iov32,
1667 			    hdtr32.hdr_cnt, &hdr_uio);
1668 			if (error)
1669 				goto out;
1670 		}
1671 		if (hdtr.trailers != NULL) {
1672 			iov32 = PTRIN(hdtr32.trailers);
1673 			error = freebsd32_copyinuio(iov32,
1674 			    hdtr32.trl_cnt, &trl_uio);
1675 			if (error)
1676 				goto out;
1677 		}
1678 	}
1679 
1680 	error = kern_sendfile(td, &ap, hdr_uio, trl_uio, compat);
1681 out:
1682 	if (hdr_uio)
1683 		free(hdr_uio, M_IOV);
1684 	if (trl_uio)
1685 		free(trl_uio, M_IOV);
1686 	return (error);
1687 }
1688 
1689 #ifdef COMPAT_FREEBSD4
1690 int
1691 freebsd4_freebsd32_sendfile(struct thread *td,
1692     struct freebsd4_freebsd32_sendfile_args *uap)
1693 {
1694 	return (freebsd32_do_sendfile(td,
1695 	    (struct freebsd32_sendfile_args *)uap, 1));
1696 }
1697 #endif
1698 
1699 int
1700 freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
1701 {
1702 
1703 	return (freebsd32_do_sendfile(td, uap, 0));
1704 }
1705 
1706 struct stat32 {
1707 	dev_t	st_dev;
1708 	ino_t	st_ino;
1709 	mode_t	st_mode;
1710 	nlink_t	st_nlink;
1711 	uid_t	st_uid;
1712 	gid_t	st_gid;
1713 	dev_t	st_rdev;
1714 	struct timespec32 st_atimespec;
1715 	struct timespec32 st_mtimespec;
1716 	struct timespec32 st_ctimespec;
1717 	off_t	st_size;
1718 	int64_t	st_blocks;
1719 	u_int32_t st_blksize;
1720 	u_int32_t st_flags;
1721 	u_int32_t st_gen;
1722 	struct timespec32 st_birthtimespec;
1723 	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1724 	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1725 };
1726 
1727 
1728 CTASSERT(sizeof(struct stat32) == 96);
1729 
1730 static void
1731 copy_stat( struct stat *in, struct stat32 *out)
1732 {
1733 	CP(*in, *out, st_dev);
1734 	CP(*in, *out, st_ino);
1735 	CP(*in, *out, st_mode);
1736 	CP(*in, *out, st_nlink);
1737 	CP(*in, *out, st_uid);
1738 	CP(*in, *out, st_gid);
1739 	CP(*in, *out, st_rdev);
1740 	TS_CP(*in, *out, st_atimespec);
1741 	TS_CP(*in, *out, st_mtimespec);
1742 	TS_CP(*in, *out, st_ctimespec);
1743 	CP(*in, *out, st_size);
1744 	CP(*in, *out, st_blocks);
1745 	CP(*in, *out, st_blksize);
1746 	CP(*in, *out, st_flags);
1747 	CP(*in, *out, st_gen);
1748 }
1749 
1750 int
1751 freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
1752 {
1753 	struct stat sb;
1754 	struct stat32 sb32;
1755 	int error;
1756 
1757 	error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
1758 	if (error)
1759 		return (error);
1760 	copy_stat(&sb, &sb32);
1761 	error = copyout(&sb32, uap->ub, sizeof (sb32));
1762 	return (error);
1763 }
1764 
1765 int
1766 freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
1767 {
1768 	struct stat ub;
1769 	struct stat32 ub32;
1770 	int error;
1771 
1772 	error = kern_fstat(td, uap->fd, &ub);
1773 	if (error)
1774 		return (error);
1775 	copy_stat(&ub, &ub32);
1776 	error = copyout(&ub32, uap->ub, sizeof(ub32));
1777 	return (error);
1778 }
1779 
1780 int
1781 freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
1782 {
1783 	struct stat sb;
1784 	struct stat32 sb32;
1785 	int error;
1786 
1787 	error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
1788 	if (error)
1789 		return (error);
1790 	copy_stat(&sb, &sb32);
1791 	error = copyout(&sb32, uap->ub, sizeof (sb32));
1792 	return (error);
1793 }
1794 
1795 /*
1796  * MPSAFE
1797  */
1798 int
1799 freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
1800 {
1801 	int error, name[CTL_MAXNAME];
1802 	size_t j, oldlen;
1803 
1804 	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1805 		return (EINVAL);
1806  	error = copyin(uap->name, name, uap->namelen * sizeof(int));
1807  	if (error)
1808 		return (error);
1809 	mtx_lock(&Giant);
1810 	if (uap->oldlenp)
1811 		oldlen = fuword32(uap->oldlenp);
1812 	else
1813 		oldlen = 0;
1814 	error = userland_sysctl(td, name, uap->namelen,
1815 		uap->old, &oldlen, 1,
1816 		uap->new, uap->newlen, &j, SCTL_MASK32);
1817 	if (error && error != ENOMEM)
1818 		goto done2;
1819 	if (uap->oldlenp)
1820 		suword32(uap->oldlenp, j);
1821 done2:
1822 	mtx_unlock(&Giant);
1823 	return (error);
1824 }
1825 
1826 struct sigaction32 {
1827 	u_int32_t	sa_u;
1828 	int		sa_flags;
1829 	sigset_t	sa_mask;
1830 };
1831 
1832 CTASSERT(sizeof(struct sigaction32) == 24);
1833 
1834 int
1835 freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
1836 {
1837 	struct sigaction32 s32;
1838 	struct sigaction sa, osa, *sap;
1839 	int error;
1840 
1841 	if (uap->act) {
1842 		error = copyin(uap->act, &s32, sizeof(s32));
1843 		if (error)
1844 			return (error);
1845 		sa.sa_handler = PTRIN(s32.sa_u);
1846 		CP(s32, sa, sa_flags);
1847 		CP(s32, sa, sa_mask);
1848 		sap = &sa;
1849 	} else
1850 		sap = NULL;
1851 	error = kern_sigaction(td, uap->sig, sap, &osa, 0);
1852 	if (error == 0 && uap->oact != NULL) {
1853 		s32.sa_u = PTROUT(osa.sa_handler);
1854 		CP(osa, s32, sa_flags);
1855 		CP(osa, s32, sa_mask);
1856 		error = copyout(&s32, uap->oact, sizeof(s32));
1857 	}
1858 	return (error);
1859 }
1860 
1861 #ifdef COMPAT_FREEBSD4
1862 int
1863 freebsd4_freebsd32_sigaction(struct thread *td,
1864 			     struct freebsd4_freebsd32_sigaction_args *uap)
1865 {
1866 	struct sigaction32 s32;
1867 	struct sigaction sa, osa, *sap;
1868 	int error;
1869 
1870 	if (uap->act) {
1871 		error = copyin(uap->act, &s32, sizeof(s32));
1872 		if (error)
1873 			return (error);
1874 		sa.sa_handler = PTRIN(s32.sa_u);
1875 		CP(s32, sa, sa_flags);
1876 		CP(s32, sa, sa_mask);
1877 		sap = &sa;
1878 	} else
1879 		sap = NULL;
1880 	error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
1881 	if (error == 0 && uap->oact != NULL) {
1882 		s32.sa_u = PTROUT(osa.sa_handler);
1883 		CP(osa, s32, sa_flags);
1884 		CP(osa, s32, sa_mask);
1885 		error = copyout(&s32, uap->oact, sizeof(s32));
1886 	}
1887 	return (error);
1888 }
1889 #endif
1890 
1891 #ifdef COMPAT_43
1892 struct osigaction32 {
1893 	u_int32_t	sa_u;
1894 	osigset_t	sa_mask;
1895 	int		sa_flags;
1896 };
1897 
1898 #define	ONSIG	32
1899 
1900 int
1901 ofreebsd32_sigaction(struct thread *td,
1902 			     struct ofreebsd32_sigaction_args *uap)
1903 {
1904 	struct osigaction32 s32;
1905 	struct sigaction sa, osa, *sap;
1906 	int error;
1907 
1908 	if (uap->signum <= 0 || uap->signum >= ONSIG)
1909 		return (EINVAL);
1910 
1911 	if (uap->nsa) {
1912 		error = copyin(uap->nsa, &s32, sizeof(s32));
1913 		if (error)
1914 			return (error);
1915 		sa.sa_handler = PTRIN(s32.sa_u);
1916 		CP(s32, sa, sa_flags);
1917 		OSIG2SIG(s32.sa_mask, sa.sa_mask);
1918 		sap = &sa;
1919 	} else
1920 		sap = NULL;
1921 	error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
1922 	if (error == 0 && uap->osa != NULL) {
1923 		s32.sa_u = PTROUT(osa.sa_handler);
1924 		CP(osa, s32, sa_flags);
1925 		SIG2OSIG(osa.sa_mask, s32.sa_mask);
1926 		error = copyout(&s32, uap->osa, sizeof(s32));
1927 	}
1928 	return (error);
1929 }
1930 
1931 int
1932 ofreebsd32_sigprocmask(struct thread *td,
1933 			       struct ofreebsd32_sigprocmask_args *uap)
1934 {
1935 	sigset_t set, oset;
1936 	int error;
1937 
1938 	OSIG2SIG(uap->mask, set);
1939 	error = kern_sigprocmask(td, uap->how, &set, &oset, 1);
1940 	SIG2OSIG(oset, td->td_retval[0]);
1941 	return (error);
1942 }
1943 
1944 int
1945 ofreebsd32_sigpending(struct thread *td,
1946 			      struct ofreebsd32_sigpending_args *uap)
1947 {
1948 	struct proc *p = td->td_proc;
1949 	sigset_t siglist;
1950 
1951 	PROC_LOCK(p);
1952 	siglist = p->p_siglist;
1953 	SIGSETOR(siglist, td->td_siglist);
1954 	PROC_UNLOCK(p);
1955 	SIG2OSIG(siglist, td->td_retval[0]);
1956 	return (0);
1957 }
1958 
1959 struct sigvec32 {
1960 	u_int32_t	sv_handler;
1961 	int		sv_mask;
1962 	int		sv_flags;
1963 };
1964 
1965 int
1966 ofreebsd32_sigvec(struct thread *td,
1967 			  struct ofreebsd32_sigvec_args *uap)
1968 {
1969 	struct sigvec32 vec;
1970 	struct sigaction sa, osa, *sap;
1971 	int error;
1972 
1973 	if (uap->signum <= 0 || uap->signum >= ONSIG)
1974 		return (EINVAL);
1975 
1976 	if (uap->nsv) {
1977 		error = copyin(uap->nsv, &vec, sizeof(vec));
1978 		if (error)
1979 			return (error);
1980 		sa.sa_handler = PTRIN(vec.sv_handler);
1981 		OSIG2SIG(vec.sv_mask, sa.sa_mask);
1982 		sa.sa_flags = vec.sv_flags;
1983 		sa.sa_flags ^= SA_RESTART;
1984 		sap = &sa;
1985 	} else
1986 		sap = NULL;
1987 	error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
1988 	if (error == 0 && uap->osv != NULL) {
1989 		vec.sv_handler = PTROUT(osa.sa_handler);
1990 		SIG2OSIG(osa.sa_mask, vec.sv_mask);
1991 		vec.sv_flags = osa.sa_flags;
1992 		vec.sv_flags &= ~SA_NOCLDWAIT;
1993 		vec.sv_flags ^= SA_RESTART;
1994 		error = copyout(&vec, uap->osv, sizeof(vec));
1995 	}
1996 	return (error);
1997 }
1998 
1999 int
2000 ofreebsd32_sigblock(struct thread *td,
2001 			    struct ofreebsd32_sigblock_args *uap)
2002 {
2003 	struct proc *p = td->td_proc;
2004 	sigset_t set;
2005 
2006 	OSIG2SIG(uap->mask, set);
2007 	SIG_CANTMASK(set);
2008 	PROC_LOCK(p);
2009 	SIG2OSIG(td->td_sigmask, td->td_retval[0]);
2010 	SIGSETOR(td->td_sigmask, set);
2011 	PROC_UNLOCK(p);
2012 	return (0);
2013 }
2014 
2015 int
2016 ofreebsd32_sigsetmask(struct thread *td,
2017 			      struct ofreebsd32_sigsetmask_args *uap)
2018 {
2019 	struct proc *p = td->td_proc;
2020 	sigset_t set;
2021 
2022 	OSIG2SIG(uap->mask, set);
2023 	SIG_CANTMASK(set);
2024 	PROC_LOCK(p);
2025 	SIG2OSIG(td->td_sigmask, td->td_retval[0]);
2026 	SIGSETLO(td->td_sigmask, set);
2027 	signotify(td);
2028 	PROC_UNLOCK(p);
2029 	return (0);
2030 }
2031 
2032 int
2033 ofreebsd32_sigsuspend(struct thread *td,
2034 			      struct ofreebsd32_sigsuspend_args *uap)
2035 {
2036 	struct proc *p = td->td_proc;
2037 	sigset_t mask;
2038 
2039 	PROC_LOCK(p);
2040 	td->td_oldsigmask = td->td_sigmask;
2041 	td->td_pflags |= TDP_OLDMASK;
2042 	OSIG2SIG(uap->mask, mask);
2043 	SIG_CANTMASK(mask);
2044 	SIGSETLO(td->td_sigmask, mask);
2045 	signotify(td);
2046 	while (msleep(&p->p_sigacts, &p->p_mtx, PPAUSE|PCATCH, "opause", 0) == 0)
2047 		/* void */;
2048 	PROC_UNLOCK(p);
2049 	/* always return EINTR rather than ERESTART... */
2050 	return (EINTR);
2051 }
2052 
2053 struct sigstack32 {
2054 	u_int32_t	ss_sp;
2055 	int		ss_onstack;
2056 };
2057 
2058 int
2059 ofreebsd32_sigstack(struct thread *td,
2060 			    struct ofreebsd32_sigstack_args *uap)
2061 {
2062 	struct sigstack32 s32;
2063 	struct sigstack nss, oss;
2064 	int error = 0;
2065 
2066 	if (uap->nss != NULL) {
2067 		error = copyin(uap->nss, &s32, sizeof(s32));
2068 		if (error)
2069 			return (error);
2070 		nss.ss_sp = PTRIN(s32.ss_sp);
2071 		CP(s32, nss, ss_onstack);
2072 	}
2073 	oss.ss_sp = td->td_sigstk.ss_sp;
2074 	oss.ss_onstack = sigonstack(cpu_getstack(td));
2075 	if (uap->nss != NULL) {
2076 		td->td_sigstk.ss_sp = nss.ss_sp;
2077 		td->td_sigstk.ss_size = 0;
2078 		td->td_sigstk.ss_flags |= nss.ss_onstack & SS_ONSTACK;
2079 		td->td_pflags |= TDP_ALTSTACK;
2080 	}
2081 	if (uap->oss != NULL) {
2082 		s32.ss_sp = PTROUT(oss.ss_sp);
2083 		CP(oss, s32, ss_onstack);
2084 		error = copyout(&s32, uap->oss, sizeof(s32));
2085 	}
2086 	return (error);
2087 }
2088 #endif
2089 
2090 int
2091 freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
2092 {
2093 	struct timespec32 rmt32, rqt32;
2094 	struct timespec rmt, rqt;
2095 	int error;
2096 
2097 	error = copyin(uap->rqtp, &rqt32, sizeof(rqt32));
2098 	if (error)
2099 		return (error);
2100 
2101 	CP(rqt32, rqt, tv_sec);
2102 	CP(rqt32, rqt, tv_nsec);
2103 
2104 	if (uap->rmtp &&
2105 	    !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
2106 		return (EFAULT);
2107 	error = kern_nanosleep(td, &rqt, &rmt);
2108 	if (error && uap->rmtp) {
2109 		int error2;
2110 
2111 		CP(rmt, rmt32, tv_sec);
2112 		CP(rmt, rmt32, tv_nsec);
2113 
2114 		error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt32));
2115 		if (error2)
2116 			error = error2;
2117 	}
2118 	return (error);
2119 }
2120 
2121 int
2122 freebsd32_clock_gettime(struct thread *td,
2123 			struct freebsd32_clock_gettime_args *uap)
2124 {
2125 	struct timespec	ats;
2126 	struct timespec32 ats32;
2127 	int error;
2128 
2129 	error = kern_clock_gettime(td, uap->clock_id, &ats);
2130 	if (error == 0) {
2131 		CP(ats, ats32, tv_sec);
2132 		CP(ats, ats32, tv_nsec);
2133 		error = copyout(&ats32, uap->tp, sizeof(ats32));
2134 	}
2135 	return (error);
2136 }
2137 
2138 int
2139 freebsd32_clock_settime(struct thread *td,
2140 			struct freebsd32_clock_settime_args *uap)
2141 {
2142 	struct timespec	ats;
2143 	struct timespec32 ats32;
2144 	int error;
2145 
2146 	error = copyin(uap->tp, &ats32, sizeof(ats32));
2147 	if (error)
2148 		return (error);
2149 	CP(ats32, ats, tv_sec);
2150 	CP(ats32, ats, tv_nsec);
2151 
2152 	return (kern_clock_settime(td, uap->clock_id, &ats));
2153 }
2154 
2155 int
2156 freebsd32_clock_getres(struct thread *td,
2157 		       struct freebsd32_clock_getres_args *uap)
2158 {
2159 	struct timespec	ts;
2160 	struct timespec32 ts32;
2161 	int error;
2162 
2163 	if (uap->tp == NULL)
2164 		return (0);
2165 	error = kern_clock_getres(td, uap->clock_id, &ts);
2166 	if (error == 0) {
2167 		CP(ts, ts32, tv_sec);
2168 		CP(ts, ts32, tv_nsec);
2169 		error = copyout(&ts32, uap->tp, sizeof(ts32));
2170 	}
2171 	return (error);
2172 }
2173 
2174 int
2175 freebsd32_thr_new(struct thread *td,
2176 		  struct freebsd32_thr_new_args *uap)
2177 {
2178 	struct thr_param32 param32;
2179 	struct thr_param param;
2180 	int error;
2181 
2182 	if (uap->param_size < 0 ||
2183 	    uap->param_size > sizeof(struct thr_param32))
2184 		return (EINVAL);
2185 	bzero(&param, sizeof(struct thr_param));
2186 	bzero(&param32, sizeof(struct thr_param32));
2187 	error = copyin(uap->param, &param32, uap->param_size);
2188 	if (error != 0)
2189 		return (error);
2190 	param.start_func = PTRIN(param32.start_func);
2191 	param.arg = PTRIN(param32.arg);
2192 	param.stack_base = PTRIN(param32.stack_base);
2193 	param.stack_size = param32.stack_size;
2194 	param.tls_base = PTRIN(param32.tls_base);
2195 	param.tls_size = param32.tls_size;
2196 	param.child_tid = PTRIN(param32.child_tid);
2197 	param.parent_tid = PTRIN(param32.parent_tid);
2198 	param.flags = param32.flags;
2199 	param.rtp = PTRIN(param32.rtp);
2200 	param.spare[0] = PTRIN(param32.spare[0]);
2201 	param.spare[1] = PTRIN(param32.spare[1]);
2202 	param.spare[2] = PTRIN(param32.spare[2]);
2203 
2204 	return (kern_thr_new(td, &param));
2205 }
2206 
2207 int
2208 freebsd32_thr_suspend(struct thread *td, struct freebsd32_thr_suspend_args *uap)
2209 {
2210 	struct timespec32 ts32;
2211 	struct timespec ts, *tsp;
2212 	int error;
2213 
2214 	error = 0;
2215 	tsp = NULL;
2216 	if (uap->timeout != NULL) {
2217 		error = copyin((const void *)uap->timeout, (void *)&ts32,
2218 		    sizeof(struct timespec32));
2219 		if (error != 0)
2220 			return (error);
2221 		ts.tv_sec = ts32.tv_sec;
2222 		ts.tv_nsec = ts32.tv_nsec;
2223 		tsp = &ts;
2224 	}
2225 	return (kern_thr_suspend(td, tsp));
2226 }
2227 
2228 void
2229 siginfo_to_siginfo32(siginfo_t *src, struct siginfo32 *dst)
2230 {
2231 	bzero(dst, sizeof(*dst));
2232 	dst->si_signo = src->si_signo;
2233 	dst->si_errno = src->si_errno;
2234 	dst->si_code = src->si_code;
2235 	dst->si_pid = src->si_pid;
2236 	dst->si_uid = src->si_uid;
2237 	dst->si_status = src->si_status;
2238 	dst->si_addr = dst->si_addr;
2239 	dst->si_value.sigval_int = src->si_value.sival_int;
2240 	dst->si_timerid = src->si_timerid;
2241 	dst->si_overrun = src->si_overrun;
2242 }
2243 
2244 int
2245 freebsd32_sigtimedwait(struct thread *td, struct freebsd32_sigtimedwait_args *uap)
2246 {
2247 	struct timespec32 ts32;
2248 	struct timespec ts;
2249 	struct timespec *timeout;
2250 	sigset_t set;
2251 	ksiginfo_t ksi;
2252 	struct siginfo32 si32;
2253 	int error;
2254 
2255 	if (uap->timeout) {
2256 		error = copyin(uap->timeout, &ts32, sizeof(ts32));
2257 		if (error)
2258 			return (error);
2259 		ts.tv_sec = ts32.tv_sec;
2260 		ts.tv_nsec = ts32.tv_nsec;
2261 		timeout = &ts;
2262 	} else
2263 		timeout = NULL;
2264 
2265 	error = copyin(uap->set, &set, sizeof(set));
2266 	if (error)
2267 		return (error);
2268 
2269 	error = kern_sigtimedwait(td, set, &ksi, timeout);
2270 	if (error)
2271 		return (error);
2272 
2273 	if (uap->info) {
2274 		siginfo_to_siginfo32(&ksi.ksi_info, &si32);
2275 		error = copyout(&si32, uap->info, sizeof(struct siginfo32));
2276 	}
2277 
2278 	if (error == 0)
2279 		td->td_retval[0] = ksi.ksi_signo;
2280 	return (error);
2281 }
2282 
2283 /*
2284  * MPSAFE
2285  */
2286 int
2287 freebsd32_sigwaitinfo(struct thread *td, struct freebsd32_sigwaitinfo_args *uap)
2288 {
2289 	ksiginfo_t ksi;
2290 	struct siginfo32 si32;
2291 	sigset_t set;
2292 	int error;
2293 
2294 	error = copyin(uap->set, &set, sizeof(set));
2295 	if (error)
2296 		return (error);
2297 
2298 	error = kern_sigtimedwait(td, set, &ksi, NULL);
2299 	if (error)
2300 		return (error);
2301 
2302 	if (uap->info) {
2303 		siginfo_to_siginfo32(&ksi.ksi_info, &si32);
2304 		error = copyout(&si32, uap->info, sizeof(struct siginfo32));
2305 	}
2306 	if (error == 0)
2307 		td->td_retval[0] = ksi.ksi_signo;
2308 	return (error);
2309 }
2310 
2311 #if 0
2312 
2313 int
2314 freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
2315 {
2316 	int error;
2317 	struct yyy32 *p32, s32;
2318 	struct yyy *p = NULL, s;
2319 
2320 	if (uap->zzz) {
2321 		error = copyin(uap->zzz, &s32, sizeof(s32));
2322 		if (error)
2323 			return (error);
2324 		/* translate in */
2325 		p = &s;
2326 	}
2327 	error = kern_xxx(td, p);
2328 	if (error)
2329 		return (error);
2330 	if (uap->zzz) {
2331 		/* translate out */
2332 		error = copyout(&s32, p32, sizeof(s32));
2333 	}
2334 	return (error);
2335 }
2336 
2337 #endif
2338