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