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