freebsd32_misc.c revision 151720
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 151720 2005-10-26 22:19:51Z peter $");
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/lock.h>
42#include <sys/malloc.h>
43#include <sys/file.h>		/* Must come after sys/malloc.h */
44#include <sys/mman.h>
45#include <sys/module.h>
46#include <sys/mount.h>
47#include <sys/mutex.h>
48#include <sys/namei.h>
49#include <sys/param.h>
50#include <sys/proc.h>
51#include <sys/reboot.h>
52#include <sys/resource.h>
53#include <sys/resourcevar.h>
54#include <sys/selinfo.h>
55#include <sys/eventvar.h>	/* Must come after sys/selinfo.h */
56#include <sys/pipe.h>		/* Must come after sys/selinfo.h */
57#include <sys/signal.h>
58#include <sys/signalvar.h>
59#include <sys/socket.h>
60#include <sys/socketvar.h>
61#include <sys/stat.h>
62#include <sys/syscall.h>
63#include <sys/syscallsubr.h>
64#include <sys/sysctl.h>
65#include <sys/sysent.h>
66#include <sys/sysproto.h>
67#include <sys/systm.h>
68#include <sys/unistd.h>
69#include <sys/vnode.h>
70#include <sys/wait.h>
71
72#include <vm/vm.h>
73#include <vm/vm_kern.h>
74#include <vm/vm_param.h>
75#include <vm/pmap.h>
76#include <vm/vm_map.h>
77#include <vm/vm_object.h>
78#include <vm/vm_extern.h>
79
80#include <machine/cpu.h>
81
82#include <compat/freebsd32/freebsd32_util.h>
83#include <compat/freebsd32/freebsd32.h>
84#include <compat/freebsd32/freebsd32_proto.h>
85
86CTASSERT(sizeof(struct timeval32) == 8);
87CTASSERT(sizeof(struct timespec32) == 8);
88CTASSERT(sizeof(struct statfs32) == 256);
89CTASSERT(sizeof(struct rusage32) == 72);
90
91int
92freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
93{
94	int error, status;
95	struct rusage32 ru32;
96	struct rusage ru, *rup;
97
98	if (uap->rusage != NULL)
99		rup = &ru;
100	else
101		rup = NULL;
102	error = kern_wait(td, uap->pid, &status, uap->options, rup);
103	if (error)
104		return (error);
105	if (uap->status != NULL)
106		error = copyout(&status, uap->status, sizeof(status));
107	if (uap->rusage != NULL && error == 0) {
108		TV_CP(ru, ru32, ru_utime);
109		TV_CP(ru, ru32, ru_stime);
110		CP(ru, ru32, ru_maxrss);
111		CP(ru, ru32, ru_ixrss);
112		CP(ru, ru32, ru_idrss);
113		CP(ru, ru32, ru_isrss);
114		CP(ru, ru32, ru_minflt);
115		CP(ru, ru32, ru_majflt);
116		CP(ru, ru32, ru_nswap);
117		CP(ru, ru32, ru_inblock);
118		CP(ru, ru32, ru_oublock);
119		CP(ru, ru32, ru_msgsnd);
120		CP(ru, ru32, ru_msgrcv);
121		CP(ru, ru32, ru_nsignals);
122		CP(ru, ru32, ru_nvcsw);
123		CP(ru, ru32, ru_nivcsw);
124		error = copyout(&ru32, uap->rusage, sizeof(ru32));
125	}
126	return (error);
127}
128
129#ifdef COMPAT_FREEBSD4
130static void
131copy_statfs(struct statfs *in, struct statfs32 *out)
132{
133	CP(*in, *out, f_bsize);
134	CP(*in, *out, f_iosize);
135	CP(*in, *out, f_blocks);
136	CP(*in, *out, f_bfree);
137	CP(*in, *out, f_bavail);
138	CP(*in, *out, f_files);
139	CP(*in, *out, f_ffree);
140	CP(*in, *out, f_fsid);
141	CP(*in, *out, f_owner);
142	CP(*in, *out, f_type);
143	CP(*in, *out, f_flags);
144	CP(*in, *out, f_flags);
145	CP(*in, *out, f_syncwrites);
146	CP(*in, *out, f_asyncwrites);
147	bcopy(in->f_fstypename,
148	      out->f_fstypename, MFSNAMELEN);
149	bcopy(in->f_mntonname,
150	      out->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN));
151	CP(*in, *out, f_syncreads);
152	CP(*in, *out, f_asyncreads);
153	bcopy(in->f_mntfromname,
154	      out->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN));
155}
156#endif
157
158#ifdef COMPAT_FREEBSD4
159int
160freebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap)
161{
162	struct statfs *buf, *sp;
163	struct statfs32 stat32;
164	size_t count, size;
165	int error;
166
167	count = uap->bufsize / sizeof(struct statfs32);
168	size = count * sizeof(struct statfs);
169	error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags);
170	if (size > 0) {
171		count = td->td_retval[0];
172		sp = buf;
173		while (count > 0 && error == 0) {
174			copy_statfs(sp, &stat32);
175			error = copyout(&stat32, uap->buf, sizeof(stat32));
176			sp++;
177			uap->buf++;
178			count--;
179		}
180		free(buf, M_TEMP);
181	}
182	return (error);
183}
184#endif
185
186struct sigaltstack32 {
187	u_int32_t	ss_sp;
188	u_int32_t	ss_size;
189	int		ss_flags;
190};
191
192CTASSERT(sizeof(struct sigaltstack32) == 12);
193
194int
195freebsd32_sigaltstack(struct thread *td,
196		      struct freebsd32_sigaltstack_args *uap)
197{
198	struct sigaltstack32 s32;
199	struct sigaltstack ss, oss, *ssp;
200	int error;
201
202	if (uap->ss != NULL) {
203		error = copyin(uap->ss, &s32, sizeof(s32));
204		if (error)
205			return (error);
206		PTRIN_CP(s32, ss, ss_sp);
207		CP(s32, ss, ss_size);
208		CP(s32, ss, ss_flags);
209		ssp = &ss;
210	} else
211		ssp = NULL;
212	error = kern_sigaltstack(td, ssp, &oss);
213	if (error == 0 && uap->oss != NULL) {
214		PTROUT_CP(oss, s32, ss_sp);
215		CP(oss, s32, ss_size);
216		CP(oss, s32, ss_flags);
217		error = copyout(&s32, uap->oss, sizeof(s32));
218	}
219	return (error);
220}
221
222/*
223 * Custom version of exec_copyin_args() so that we can translate
224 * the pointers.
225 */
226static int
227freebsd32_exec_copyin_args(struct image_args *args, char *fname,
228    enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv)
229{
230	char *argp, *envp;
231	u_int32_t *p32, arg;
232	size_t length;
233	int error;
234
235	bzero(args, sizeof(*args));
236	if (argv == NULL)
237		return (EFAULT);
238
239	/*
240	 * Allocate temporary demand zeroed space for argument and
241	 *	environment strings
242	 */
243	args->buf = (char *) kmem_alloc_wait(exec_map,
244	    PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
245	if (args->buf == NULL)
246		return (ENOMEM);
247	args->begin_argv = args->buf;
248	args->endp = args->begin_argv;
249	args->stringspace = ARG_MAX;
250
251	args->fname = args->buf + ARG_MAX;
252
253	/*
254	 * Copy the file name.
255	 */
256	error = (segflg == UIO_SYSSPACE) ?
257	    copystr(fname, args->fname, PATH_MAX, &length) :
258	    copyinstr(fname, args->fname, PATH_MAX, &length);
259	if (error != 0)
260		return (error);
261
262	/*
263	 * extract arguments first
264	 */
265	p32 = argv;
266	for (;;) {
267		error = copyin(p32++, &arg, sizeof(arg));
268		if (error)
269			return (error);
270		if (arg == 0)
271			break;
272		argp = PTRIN(arg);
273		error = copyinstr(argp, args->endp, args->stringspace, &length);
274		if (error) {
275			if (error == ENAMETOOLONG)
276				return (E2BIG);
277			else
278				return (error);
279		}
280		args->stringspace -= length;
281		args->endp += length;
282		args->argc++;
283	}
284
285	args->begin_envv = args->endp;
286
287	/*
288	 * extract environment strings
289	 */
290	if (envv) {
291		p32 = envv;
292		for (;;) {
293			error = copyin(p32++, &arg, sizeof(arg));
294			if (error)
295				return (error);
296			if (arg == 0)
297				break;
298			envp = PTRIN(arg);
299			error = copyinstr(envp, args->endp, args->stringspace,
300			    &length);
301			if (error) {
302				if (error == ENAMETOOLONG)
303					return (E2BIG);
304				else
305					return (error);
306			}
307			args->stringspace -= length;
308			args->endp += length;
309			args->envc++;
310		}
311	}
312
313	return (0);
314}
315
316int
317freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
318{
319	struct image_args eargs;
320	int error;
321
322	error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE,
323	    uap->argv, uap->envv);
324	if (error == 0)
325		error = kern_execve(td, &eargs, NULL);
326	exec_free_args(&eargs);
327	return (error);
328}
329
330#ifdef __ia64__
331static int
332freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
333		       int prot, int fd, off_t pos)
334{
335	vm_map_t map;
336	vm_map_entry_t entry;
337	int rv;
338
339	map = &td->td_proc->p_vmspace->vm_map;
340	if (fd != -1)
341		prot |= VM_PROT_WRITE;
342
343	if (vm_map_lookup_entry(map, start, &entry)) {
344		if ((entry->protection & prot) != prot) {
345			rv = vm_map_protect(map,
346					    trunc_page(start),
347					    round_page(end),
348					    entry->protection | prot,
349					    FALSE);
350			if (rv != KERN_SUCCESS)
351				return (EINVAL);
352		}
353	} else {
354		vm_offset_t addr = trunc_page(start);
355		rv = vm_map_find(map, 0, 0,
356				 &addr, PAGE_SIZE, FALSE, prot,
357				 VM_PROT_ALL, 0);
358		if (rv != KERN_SUCCESS)
359			return (EINVAL);
360	}
361
362	if (fd != -1) {
363		struct pread_args r;
364		r.fd = fd;
365		r.buf = (void *) start;
366		r.nbyte = end - start;
367		r.offset = pos;
368		return (pread(td, &r));
369	} else {
370		while (start < end) {
371			subyte((void *) start, 0);
372			start++;
373		}
374		return (0);
375	}
376}
377#endif
378
379int
380freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
381{
382	struct mmap_args ap;
383	vm_offset_t addr = (vm_offset_t) uap->addr;
384	vm_size_t len	 = uap->len;
385	int prot	 = uap->prot;
386	int flags	 = uap->flags;
387	int fd		 = uap->fd;
388	off_t pos	 = (uap->poslo
389			    | ((off_t)uap->poshi << 32));
390#ifdef __ia64__
391	vm_size_t pageoff;
392	int error;
393
394	/*
395	 * Attempt to handle page size hassles.
396	 */
397	pageoff = (pos & PAGE_MASK);
398	if (flags & MAP_FIXED) {
399		vm_offset_t start, end;
400		start = addr;
401		end = addr + len;
402
403		mtx_lock(&Giant);
404		if (start != trunc_page(start)) {
405			error = freebsd32_mmap_partial(td, start,
406						       round_page(start), prot,
407						       fd, pos);
408			if (fd != -1)
409				pos += round_page(start) - start;
410			start = round_page(start);
411		}
412		if (end != round_page(end)) {
413			vm_offset_t t = trunc_page(end);
414			error = freebsd32_mmap_partial(td, t, end,
415						  prot, fd,
416						  pos + t - start);
417			end = trunc_page(end);
418		}
419		if (end > start && fd != -1 && (pos & PAGE_MASK)) {
420			/*
421			 * We can't map this region at all. The specified
422			 * address doesn't have the same alignment as the file
423			 * position. Fake the mapping by simply reading the
424			 * entire region into memory. First we need to make
425			 * sure the region exists.
426			 */
427			vm_map_t map;
428			struct pread_args r;
429			int rv;
430
431			prot |= VM_PROT_WRITE;
432			map = &td->td_proc->p_vmspace->vm_map;
433			rv = vm_map_remove(map, start, end);
434			if (rv != KERN_SUCCESS) {
435				mtx_unlock(&Giant);
436				return (EINVAL);
437			}
438			rv = vm_map_find(map, 0, 0,
439					 &start, end - start, FALSE,
440					 prot, VM_PROT_ALL, 0);
441			mtx_unlock(&Giant);
442			if (rv != KERN_SUCCESS)
443				return (EINVAL);
444			r.fd = fd;
445			r.buf = (void *) start;
446			r.nbyte = end - start;
447			r.offset = pos;
448			error = pread(td, &r);
449			if (error)
450				return (error);
451
452			td->td_retval[0] = addr;
453			return (0);
454		}
455		mtx_unlock(&Giant);
456		if (end == start) {
457			/*
458			 * After dealing with the ragged ends, there
459			 * might be none left.
460			 */
461			td->td_retval[0] = addr;
462			return (0);
463		}
464		addr = start;
465		len = end - start;
466	}
467#endif
468
469	ap.addr = (void *) addr;
470	ap.len = len;
471	ap.prot = prot;
472	ap.flags = flags;
473	ap.fd = fd;
474	ap.pos = pos;
475
476	return (mmap(td, &ap));
477}
478
479struct itimerval32 {
480	struct timeval32 it_interval;
481	struct timeval32 it_value;
482};
483
484CTASSERT(sizeof(struct itimerval32) == 16);
485
486int
487freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
488{
489	struct itimerval itv, oitv, *itvp;
490	struct itimerval32 i32;
491	int error;
492
493	if (uap->itv != NULL) {
494		error = copyin(uap->itv, &i32, sizeof(i32));
495		if (error)
496			return (error);
497		TV_CP(i32, itv, it_interval);
498		TV_CP(i32, itv, it_value);
499		itvp = &itv;
500	} else
501		itvp = NULL;
502	error = kern_setitimer(td, uap->which, itvp, &oitv);
503	if (error || uap->oitv == NULL)
504		return (error);
505	TV_CP(oitv, i32, it_interval);
506	TV_CP(oitv, i32, it_value);
507	return (copyout(&i32, uap->oitv, sizeof(i32)));
508}
509
510int
511freebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)
512{
513	struct itimerval itv;
514	struct itimerval32 i32;
515	int error;
516
517	error = kern_getitimer(td, uap->which, &itv);
518	if (error || uap->itv == NULL)
519		return (error);
520	TV_CP(itv, i32, it_interval);
521	TV_CP(itv, i32, it_value);
522	return (copyout(&i32, uap->itv, sizeof(i32)));
523}
524
525int
526freebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
527{
528	struct timeval32 tv32;
529	struct timeval tv, *tvp;
530	int error;
531
532	if (uap->tv != NULL) {
533		error = copyin(uap->tv, &tv32, sizeof(tv32));
534		if (error)
535			return (error);
536		CP(tv32, tv, tv_sec);
537		CP(tv32, tv, tv_usec);
538		tvp = &tv;
539	} else
540		tvp = NULL;
541	/*
542	 * XXX big-endian needs to convert the fd_sets too.
543	 * XXX Do pointers need PTRIN()?
544	 */
545	return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp));
546}
547
548struct kevent32 {
549	u_int32_t	ident;		/* identifier for this event */
550	short		filter;		/* filter for event */
551	u_short		flags;
552	u_int		fflags;
553	int32_t		data;
554	u_int32_t	udata;		/* opaque user data identifier */
555};
556
557CTASSERT(sizeof(struct kevent32) == 20);
558static int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);
559static int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count);
560
561/*
562 * Copy 'count' items into the destination list pointed to by uap->eventlist.
563 */
564static int
565freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count)
566{
567	struct freebsd32_kevent_args *uap;
568	struct kevent32	ks32[KQ_NEVENTS];
569	int i, error = 0;
570
571	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
572	uap = (struct freebsd32_kevent_args *)arg;
573
574	for (i = 0; i < count; i++) {
575		CP(kevp[i], ks32[i], ident);
576		CP(kevp[i], ks32[i], filter);
577		CP(kevp[i], ks32[i], flags);
578		CP(kevp[i], ks32[i], fflags);
579		CP(kevp[i], ks32[i], data);
580		PTROUT_CP(kevp[i], ks32[i], udata);
581	}
582	error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
583	if (error == 0)
584		uap->eventlist += count;
585	return (error);
586}
587
588/*
589 * Copy 'count' items from the list pointed to by uap->changelist.
590 */
591static int
592freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)
593{
594	struct freebsd32_kevent_args *uap;
595	struct kevent32	ks32[KQ_NEVENTS];
596	int i, error = 0;
597
598	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
599	uap = (struct freebsd32_kevent_args *)arg;
600
601	error = copyin(uap->changelist, ks32, count * sizeof *ks32);
602	if (error)
603		goto done;
604	uap->changelist += count;
605
606	for (i = 0; i < count; i++) {
607		CP(ks32[i], kevp[i], ident);
608		CP(ks32[i], kevp[i], filter);
609		CP(ks32[i], kevp[i], flags);
610		CP(ks32[i], kevp[i], fflags);
611		CP(ks32[i], kevp[i], data);
612		PTRIN_CP(ks32[i], kevp[i], udata);
613	}
614done:
615	return (error);
616}
617
618int
619freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
620{
621	struct timespec32 ts32;
622	struct timespec ts, *tsp;
623	struct kevent_copyops k_ops = { uap,
624					freebsd32_kevent_copyout,
625					freebsd32_kevent_copyin};
626	int error;
627
628
629	if (uap->timeout) {
630		error = copyin(uap->timeout, &ts32, sizeof(ts32));
631		if (error)
632			return (error);
633		CP(ts32, ts, tv_sec);
634		CP(ts32, ts, tv_nsec);
635		tsp = &ts;
636	} else
637		tsp = NULL;
638	error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,
639	    &k_ops, tsp);
640	return (error);
641}
642
643int
644freebsd32_gettimeofday(struct thread *td,
645		       struct freebsd32_gettimeofday_args *uap)
646{
647	struct timeval atv;
648	struct timeval32 atv32;
649	struct timezone rtz;
650	int error = 0;
651
652	if (uap->tp) {
653		microtime(&atv);
654		CP(atv, atv32, tv_sec);
655		CP(atv, atv32, tv_usec);
656		error = copyout(&atv32, uap->tp, sizeof (atv32));
657	}
658	if (error == 0 && uap->tzp != NULL) {
659		rtz.tz_minuteswest = tz_minuteswest;
660		rtz.tz_dsttime = tz_dsttime;
661		error = copyout(&rtz, uap->tzp, sizeof (rtz));
662	}
663	return (error);
664}
665
666int
667freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
668{
669	struct rusage32 s32;
670	struct rusage s;
671	int error;
672
673	error = kern_getrusage(td, uap->who, &s);
674	if (error)
675		return (error);
676	if (uap->rusage != NULL) {
677		TV_CP(s, s32, ru_utime);
678		TV_CP(s, s32, ru_stime);
679		CP(s, s32, ru_maxrss);
680		CP(s, s32, ru_ixrss);
681		CP(s, s32, ru_idrss);
682		CP(s, s32, ru_isrss);
683		CP(s, s32, ru_minflt);
684		CP(s, s32, ru_majflt);
685		CP(s, s32, ru_nswap);
686		CP(s, s32, ru_inblock);
687		CP(s, s32, ru_oublock);
688		CP(s, s32, ru_msgsnd);
689		CP(s, s32, ru_msgrcv);
690		CP(s, s32, ru_nsignals);
691		CP(s, s32, ru_nvcsw);
692		CP(s, s32, ru_nivcsw);
693		error = copyout(&s32, uap->rusage, sizeof(s32));
694	}
695	return (error);
696}
697
698struct iovec32 {
699	u_int32_t iov_base;
700	int	iov_len;
701};
702
703CTASSERT(sizeof(struct iovec32) == 8);
704
705static int
706freebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
707{
708	struct iovec32 iov32;
709	struct iovec *iov;
710	struct uio *uio;
711	u_int iovlen;
712	int error, i;
713
714	*uiop = NULL;
715	if (iovcnt > UIO_MAXIOV)
716		return (EINVAL);
717	iovlen = iovcnt * sizeof(struct iovec);
718	uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
719	iov = (struct iovec *)(uio + 1);
720	for (i = 0; i < iovcnt; i++) {
721		error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
722		if (error) {
723			free(uio, M_IOV);
724			return (error);
725		}
726		iov[i].iov_base = PTRIN(iov32.iov_base);
727		iov[i].iov_len = iov32.iov_len;
728	}
729	uio->uio_iov = iov;
730	uio->uio_iovcnt = iovcnt;
731	uio->uio_segflg = UIO_USERSPACE;
732	uio->uio_offset = -1;
733	uio->uio_resid = 0;
734	for (i = 0; i < iovcnt; i++) {
735		if (iov->iov_len > INT_MAX - uio->uio_resid) {
736			free(uio, M_IOV);
737			return (EINVAL);
738		}
739		uio->uio_resid += iov->iov_len;
740		iov++;
741	}
742	*uiop = uio;
743	return (0);
744}
745
746int
747freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
748{
749	struct uio *auio;
750	int error;
751
752	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
753	if (error)
754		return (error);
755	error = kern_readv(td, uap->fd, auio);
756	free(auio, M_IOV);
757	return (error);
758}
759
760int
761freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
762{
763	struct uio *auio;
764	int error;
765
766	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
767	if (error)
768		return (error);
769	error = kern_writev(td, uap->fd, auio);
770	free(auio, M_IOV);
771	return (error);
772}
773
774int
775freebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap)
776{
777	struct uio *auio;
778	int error;
779
780	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
781	if (error)
782		return (error);
783	error = kern_preadv(td, uap->fd, auio, uap->offset);
784	free(auio, M_IOV);
785	return (error);
786}
787
788int
789freebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap)
790{
791	struct uio *auio;
792	int error;
793
794	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
795	if (error)
796		return (error);
797	error = kern_pwritev(td, uap->fd, auio, uap->offset);
798	free(auio, M_IOV);
799	return (error);
800}
801
802static int
803freebsd32_copyiniov(struct iovec32 *iovp, u_int iovcnt, struct iovec **iov,
804    int error)
805{
806	struct iovec32 iov32;
807	int i;
808
809	u_int iovlen;
810
811	*iov = NULL;
812	if (iovcnt > UIO_MAXIOV)
813		return (error);
814	iovlen = iovcnt * sizeof(struct iovec);
815	*iov = malloc(iovlen, M_IOV, M_WAITOK);
816	for (i = 0; i < iovcnt; i++) {
817		error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
818		if (error) {
819			free(*iov, M_IOV);
820			*iov = NULL;
821			return (error);
822		}
823		iov[i]->iov_base = PTRIN(iov32.iov_base);
824		iov[i]->iov_len = iov32.iov_len;
825	}
826	return (0);
827}
828
829struct msghdr32 {
830	u_int32_t	 msg_name;
831	socklen_t	 msg_namelen;
832	u_int32_t	 msg_iov;
833	int		 msg_iovlen;
834	u_int32_t	 msg_control;
835	socklen_t	 msg_controllen;
836	int		 msg_flags;
837};
838CTASSERT(sizeof(struct msghdr32) == 28);
839
840static int
841freebsd32_copyinmsghdr(struct msghdr32 *msg32, struct msghdr *msg)
842{
843	struct msghdr32 m32;
844	int error;
845
846	error = copyin(msg32, &m32, sizeof(m32));
847	if (error)
848		return (error);
849	msg->msg_name = PTRIN(m32.msg_name);
850	msg->msg_namelen = m32.msg_namelen;
851	msg->msg_iov = PTRIN(m32.msg_iov);
852	msg->msg_iovlen = m32.msg_iovlen;
853	msg->msg_control = PTRIN(m32.msg_control);
854	msg->msg_controllen = m32.msg_controllen;
855	msg->msg_flags = m32.msg_flags;
856	return (freebsd32_copyiniov((struct iovec32 *)(uintptr_t)m32.msg_iov, m32.msg_iovlen, &msg->msg_iov,
857	    EMSGSIZE));
858}
859
860static int
861freebsd32_copyoutmsghdr(struct msghdr *msg, struct msghdr32 *msg32)
862{
863	struct msghdr32 m32;
864	int error;
865
866	m32.msg_name = PTROUT(msg->msg_name);
867	m32.msg_namelen = msg->msg_namelen;
868	m32.msg_iov = PTROUT(msg->msg_iov);
869	m32.msg_iovlen = msg->msg_iovlen;
870	m32.msg_control = PTROUT(msg->msg_control);
871	m32.msg_controllen = msg->msg_controllen;
872	m32.msg_flags = msg->msg_flags;
873	error = copyout(&m32, msg32, sizeof(m32));
874	return (error);
875}
876
877int
878freebsd32_recvmsg(td, uap)
879	struct thread *td;
880	struct freebsd32_recvmsg_args /* {
881		int	s;
882		struct	msghdr32 *msg;
883		int	flags;
884	} */ *uap;
885{
886	struct msghdr msg;
887	struct msghdr32 m32;
888	struct iovec *uiov, *iov;
889	int error;
890
891	error = copyin(uap->msg, &m32, sizeof(m32));
892	if (error)
893		return (error);
894	error = freebsd32_copyinmsghdr(uap->msg, &msg);
895	if (error)
896		return (error);
897	error = freebsd32_copyiniov((struct iovec32 *)(uintptr_t)m32.msg_iov,
898	    m32.msg_iovlen, &iov, EMSGSIZE);
899	if (error)
900		return (error);
901	msg.msg_flags = uap->flags;
902	uiov = msg.msg_iov;
903	msg.msg_iov = iov;
904	error = kern_recvit(td, uap->s, &msg, NULL, UIO_SYSSPACE);
905	if (error == 0) {
906		msg.msg_iov = uiov;
907		error = freebsd32_copyoutmsghdr(&msg, uap->msg);
908	}
909	free(iov, M_IOV);
910	free(uiov, M_IOV);
911	return (error);
912}
913
914int
915freebsd32_sendmsg(struct thread *td,
916		  struct freebsd32_sendmsg_args *uap)
917{
918	struct msghdr msg;
919	struct msghdr32 m32;
920	struct iovec *iov;
921	int error;
922
923	error = copyin(uap->msg, &m32, sizeof(m32));
924	if (error)
925		return (error);
926	error = freebsd32_copyinmsghdr(uap->msg, &msg);
927	if (error)
928		return (error);
929	error = freebsd32_copyiniov((struct iovec32 *)(uintptr_t)m32.msg_iov,
930	    m32.msg_iovlen, &iov, EMSGSIZE);
931	if (error)
932		return (error);
933	msg.msg_iov = iov;
934	error = kern_sendit(td, uap->s, &msg, uap->flags, NULL, UIO_SYSSPACE);
935	free(iov, M_IOV);
936	return (error);
937}
938
939int
940freebsd32_recvfrom(struct thread *td,
941		   struct freebsd32_recvfrom_args *uap)
942{
943	struct msghdr msg;
944	struct iovec aiov;
945	int error;
946
947	if (uap->fromlenaddr) {
948		error = copyin((void *)(uintptr_t)uap->fromlenaddr,
949		    &msg.msg_namelen, sizeof(msg.msg_namelen));
950		if (error)
951			return (error);
952	} else {
953		msg.msg_namelen = 0;
954	}
955
956	msg.msg_name = (void *)(uintptr_t)uap->from;
957	msg.msg_iov = &aiov;
958	msg.msg_iovlen = 1;
959	aiov.iov_base = (void *)(uintptr_t)uap->buf;
960	aiov.iov_len = uap->len;
961	msg.msg_control = 0;
962	msg.msg_flags = uap->flags;
963	error = kern_recvit(td, uap->s, &msg, (void *)(uintptr_t)uap->fromlenaddr, UIO_USERSPACE);
964	return (error);
965}
966
967int
968freebsd32_settimeofday(struct thread *td,
969		       struct freebsd32_settimeofday_args *uap)
970{
971	struct timeval32 tv32;
972	struct timeval tv, *tvp;
973	struct timezone tz, *tzp;
974	int error;
975
976	if (uap->tv) {
977		error = copyin(uap->tv, &tv32, sizeof(tv32));
978		if (error)
979			return (error);
980		CP(tv32, tv, tv_sec);
981		CP(tv32, tv, tv_usec);
982		tvp = &tv;
983	} else
984		tvp = NULL;
985	if (uap->tzp) {
986		error = copyin(uap->tzp, &tz, sizeof(tz));
987		if (error)
988			return (error);
989		tzp = &tz;
990	} else
991		tzp = NULL;
992	return (kern_settimeofday(td, tvp, tzp));
993}
994
995int
996freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
997{
998	struct timeval32 s32[2];
999	struct timeval s[2], *sp;
1000	int error;
1001
1002	if (uap->tptr != NULL) {
1003		error = copyin(uap->tptr, s32, sizeof(s32));
1004		if (error)
1005			return (error);
1006		CP(s32[0], s[0], tv_sec);
1007		CP(s32[0], s[0], tv_usec);
1008		CP(s32[1], s[1], tv_sec);
1009		CP(s32[1], s[1], tv_usec);
1010		sp = s;
1011	} else
1012		sp = NULL;
1013	return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
1014}
1015
1016int
1017freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
1018{
1019	struct timeval32 tv32;
1020	struct timeval delta, olddelta, *deltap;
1021	int error;
1022
1023	if (uap->delta) {
1024		error = copyin(uap->delta, &tv32, sizeof(tv32));
1025		if (error)
1026			return (error);
1027		CP(tv32, delta, tv_sec);
1028		CP(tv32, delta, tv_usec);
1029		deltap = &delta;
1030	} else
1031		deltap = NULL;
1032	error = kern_adjtime(td, deltap, &olddelta);
1033	if (uap->olddelta && error == 0) {
1034		CP(olddelta, tv32, tv_sec);
1035		CP(olddelta, tv32, tv_usec);
1036		error = copyout(&tv32, uap->olddelta, sizeof(tv32));
1037	}
1038	return (error);
1039}
1040
1041#ifdef COMPAT_FREEBSD4
1042int
1043freebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)
1044{
1045	struct statfs32 s32;
1046	struct statfs s;
1047	int error;
1048
1049	error = kern_statfs(td, uap->path, UIO_USERSPACE, &s);
1050	if (error)
1051		return (error);
1052	copy_statfs(&s, &s32);
1053	return (copyout(&s32, uap->buf, sizeof(s32)));
1054}
1055#endif
1056
1057#ifdef COMPAT_FREEBSD4
1058int
1059freebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)
1060{
1061	struct statfs32 s32;
1062	struct statfs s;
1063	int error;
1064
1065	error = kern_fstatfs(td, uap->fd, &s);
1066	if (error)
1067		return (error);
1068	copy_statfs(&s, &s32);
1069	return (copyout(&s32, uap->buf, sizeof(s32)));
1070}
1071#endif
1072
1073#ifdef COMPAT_FREEBSD4
1074int
1075freebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)
1076{
1077	struct statfs32 s32;
1078	struct statfs s;
1079	fhandle_t fh;
1080	int error;
1081
1082	if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
1083		return (error);
1084	error = kern_fhstatfs(td, fh, &s);
1085	if (error)
1086		return (error);
1087	copy_statfs(&s, &s32);
1088	return (copyout(&s32, uap->buf, sizeof(s32)));
1089}
1090#endif
1091
1092int
1093freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
1094{
1095	/*
1096	 * Vector through to semsys if it is loaded.
1097	 */
1098	return sysent[SYS_semsys].sy_call(td, uap);
1099}
1100
1101int
1102freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
1103{
1104	/*
1105	 * Vector through to msgsys if it is loaded.
1106	 */
1107	return sysent[SYS_msgsys].sy_call(td, uap);
1108}
1109
1110int
1111freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
1112{
1113	/*
1114	 * Vector through to shmsys if it is loaded.
1115	 */
1116	return sysent[SYS_shmsys].sy_call(td, uap);
1117}
1118
1119int
1120freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
1121{
1122	struct pread_args ap;
1123
1124	ap.fd = uap->fd;
1125	ap.buf = uap->buf;
1126	ap.nbyte = uap->nbyte;
1127	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1128	return (pread(td, &ap));
1129}
1130
1131int
1132freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
1133{
1134	struct pwrite_args ap;
1135
1136	ap.fd = uap->fd;
1137	ap.buf = uap->buf;
1138	ap.nbyte = uap->nbyte;
1139	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1140	return (pwrite(td, &ap));
1141}
1142
1143int
1144freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
1145{
1146	int error;
1147	struct lseek_args ap;
1148	off_t pos;
1149
1150	ap.fd = uap->fd;
1151	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1152	ap.whence = uap->whence;
1153	error = lseek(td, &ap);
1154	/* Expand the quad return into two parts for eax and edx */
1155	pos = *(off_t *)(td->td_retval);
1156	td->td_retval[0] = pos & 0xffffffff;	/* %eax */
1157	td->td_retval[1] = pos >> 32;		/* %edx */
1158	return error;
1159}
1160
1161int
1162freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
1163{
1164	struct truncate_args ap;
1165
1166	ap.path = uap->path;
1167	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1168	return (truncate(td, &ap));
1169}
1170
1171int
1172freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
1173{
1174	struct ftruncate_args ap;
1175
1176	ap.fd = uap->fd;
1177	ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1178	return (ftruncate(td, &ap));
1179}
1180
1181#ifdef COMPAT_FREEBSD4
1182int
1183freebsd4_freebsd32_sendfile(struct thread *td,
1184    struct freebsd4_freebsd32_sendfile_args *uap)
1185{
1186	struct freebsd4_sendfile_args ap;
1187
1188	ap.fd = uap->fd;
1189	ap.s = uap->s;
1190	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1191	ap.nbytes = uap->nbytes;	/* XXX check */
1192	ap.hdtr = uap->hdtr;		/* XXX check */
1193	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1194	ap.flags = uap->flags;
1195	return (freebsd4_sendfile(td, &ap));
1196}
1197#endif
1198
1199int
1200freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
1201{
1202	struct sendfile_args ap;
1203
1204	ap.fd = uap->fd;
1205	ap.s = uap->s;
1206	ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1207	ap.nbytes = uap->nbytes;	/* XXX check */
1208	ap.hdtr = uap->hdtr;		/* XXX check */
1209	ap.sbytes = uap->sbytes;	/* XXX FIXME!! */
1210	ap.flags = uap->flags;
1211	return (sendfile(td, &ap));
1212}
1213
1214struct stat32 {
1215	dev_t	st_dev;
1216	ino_t	st_ino;
1217	mode_t	st_mode;
1218	nlink_t	st_nlink;
1219	uid_t	st_uid;
1220	gid_t	st_gid;
1221	dev_t	st_rdev;
1222	struct timespec32 st_atimespec;
1223	struct timespec32 st_mtimespec;
1224	struct timespec32 st_ctimespec;
1225	off_t	st_size;
1226	int64_t	st_blocks;
1227	u_int32_t st_blksize;
1228	u_int32_t st_flags;
1229	u_int32_t st_gen;
1230	struct timespec32 st_birthtimespec;
1231	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1232	unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1233};
1234
1235
1236CTASSERT(sizeof(struct stat32) == 96);
1237
1238static void
1239copy_stat( struct stat *in, struct stat32 *out)
1240{
1241	CP(*in, *out, st_dev);
1242	CP(*in, *out, st_ino);
1243	CP(*in, *out, st_mode);
1244	CP(*in, *out, st_nlink);
1245	CP(*in, *out, st_uid);
1246	CP(*in, *out, st_gid);
1247	CP(*in, *out, st_rdev);
1248	TS_CP(*in, *out, st_atimespec);
1249	TS_CP(*in, *out, st_mtimespec);
1250	TS_CP(*in, *out, st_ctimespec);
1251	CP(*in, *out, st_size);
1252	CP(*in, *out, st_blocks);
1253	CP(*in, *out, st_blksize);
1254	CP(*in, *out, st_flags);
1255	CP(*in, *out, st_gen);
1256}
1257
1258int
1259freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
1260{
1261	struct stat sb;
1262	struct stat32 sb32;
1263	int error;
1264
1265	error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
1266	if (error)
1267		return (error);
1268	copy_stat(&sb, &sb32);
1269	error = copyout(&sb32, uap->ub, sizeof (sb32));
1270	return (error);
1271}
1272
1273int
1274freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
1275{
1276	struct stat ub;
1277	struct stat32 ub32;
1278	int error;
1279
1280	error = kern_fstat(td, uap->fd, &ub);
1281	if (error)
1282		return (error);
1283	copy_stat(&ub, &ub32);
1284	error = copyout(&ub32, uap->ub, sizeof(ub32));
1285	return (error);
1286}
1287
1288int
1289freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
1290{
1291	struct stat sb;
1292	struct stat32 sb32;
1293	int error;
1294
1295	error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
1296	if (error)
1297		return (error);
1298	copy_stat(&sb, &sb32);
1299	error = copyout(&sb32, uap->ub, sizeof (sb32));
1300	return (error);
1301}
1302
1303/*
1304 * MPSAFE
1305 */
1306int
1307freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
1308{
1309	int error, name[CTL_MAXNAME];
1310	size_t j, oldlen;
1311
1312	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1313		return (EINVAL);
1314 	error = copyin(uap->name, name, uap->namelen * sizeof(int));
1315 	if (error)
1316		return (error);
1317	mtx_lock(&Giant);
1318	if (uap->oldlenp)
1319		oldlen = fuword32(uap->oldlenp);
1320	else
1321		oldlen = 0;
1322	error = userland_sysctl(td, name, uap->namelen,
1323		uap->old, &oldlen, 1,
1324		uap->new, uap->newlen, &j, SCTL_MASK32);
1325	if (error && error != ENOMEM)
1326		goto done2;
1327	if (uap->oldlenp)
1328		suword32(uap->oldlenp, j);
1329done2:
1330	mtx_unlock(&Giant);
1331	return (error);
1332}
1333
1334struct sigaction32 {
1335	u_int32_t	sa_u;
1336	int		sa_flags;
1337	sigset_t	sa_mask;
1338};
1339
1340CTASSERT(sizeof(struct sigaction32) == 24);
1341
1342int
1343freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
1344{
1345	struct sigaction32 s32;
1346	struct sigaction sa, osa, *sap;
1347	int error;
1348
1349	if (uap->act) {
1350		error = copyin(uap->act, &s32, sizeof(s32));
1351		if (error)
1352			return (error);
1353		sa.sa_handler = PTRIN(s32.sa_u);
1354		CP(s32, sa, sa_flags);
1355		CP(s32, sa, sa_mask);
1356		sap = &sa;
1357	} else
1358		sap = NULL;
1359	error = kern_sigaction(td, uap->sig, sap, &osa, 0);
1360	if (error == 0 && uap->oact != NULL) {
1361		s32.sa_u = PTROUT(osa.sa_handler);
1362		CP(osa, s32, sa_flags);
1363		CP(osa, s32, sa_mask);
1364		error = copyout(&s32, uap->oact, sizeof(s32));
1365	}
1366	return (error);
1367}
1368
1369#ifdef COMPAT_FREEBSD4
1370int
1371freebsd4_freebsd32_sigaction(struct thread *td,
1372			     struct freebsd4_freebsd32_sigaction_args *uap)
1373{
1374	struct sigaction32 s32;
1375	struct sigaction sa, osa, *sap;
1376	int error;
1377
1378	if (uap->act) {
1379		error = copyin(uap->act, &s32, sizeof(s32));
1380		if (error)
1381			return (error);
1382		sa.sa_handler = PTRIN(s32.sa_u);
1383		CP(s32, sa, sa_flags);
1384		CP(s32, sa, sa_mask);
1385		sap = &sa;
1386	} else
1387		sap = NULL;
1388	error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
1389	if (error == 0 && uap->oact != NULL) {
1390		s32.sa_u = PTROUT(osa.sa_handler);
1391		CP(osa, s32, sa_flags);
1392		CP(osa, s32, sa_mask);
1393		error = copyout(&s32, uap->oact, sizeof(s32));
1394	}
1395	return (error);
1396}
1397#endif
1398
1399#ifdef COMPAT_43
1400struct osigaction32 {
1401	u_int32_t	sa_u;
1402	osigset_t	sa_mask;
1403	int		sa_flags;
1404};
1405
1406#define	ONSIG	32
1407
1408int
1409ofreebsd32_sigaction(struct thread *td,
1410			     struct ofreebsd32_sigaction_args *uap)
1411{
1412	struct osigaction32 s32;
1413	struct sigaction sa, osa, *sap;
1414	int error;
1415
1416	if (uap->signum <= 0 || uap->signum >= ONSIG)
1417		return (EINVAL);
1418
1419	if (uap->nsa) {
1420		error = copyin(uap->nsa, &s32, sizeof(s32));
1421		if (error)
1422			return (error);
1423		sa.sa_handler = PTRIN(s32.sa_u);
1424		CP(s32, sa, sa_flags);
1425		OSIG2SIG(s32.sa_mask, sa.sa_mask);
1426		sap = &sa;
1427	} else
1428		sap = NULL;
1429	error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
1430	if (error == 0 && uap->osa != NULL) {
1431		s32.sa_u = PTROUT(osa.sa_handler);
1432		CP(osa, s32, sa_flags);
1433		SIG2OSIG(osa.sa_mask, s32.sa_mask);
1434		error = copyout(&s32, uap->osa, sizeof(s32));
1435	}
1436	return (error);
1437}
1438
1439int
1440ofreebsd32_sigprocmask(struct thread *td,
1441			       struct ofreebsd32_sigprocmask_args *uap)
1442{
1443	sigset_t set, oset;
1444	int error;
1445
1446	OSIG2SIG(uap->mask, set);
1447	error = kern_sigprocmask(td, uap->how, &set, &oset, 1);
1448	SIG2OSIG(oset, td->td_retval[0]);
1449	return (error);
1450}
1451
1452int
1453ofreebsd32_sigpending(struct thread *td,
1454			      struct ofreebsd32_sigpending_args *uap)
1455{
1456	struct proc *p = td->td_proc;
1457	sigset_t siglist;
1458
1459	PROC_LOCK(p);
1460	siglist = p->p_siglist;
1461	SIGSETOR(siglist, td->td_siglist);
1462	PROC_UNLOCK(p);
1463	SIG2OSIG(siglist, td->td_retval[0]);
1464	return (0);
1465}
1466
1467struct sigvec32 {
1468	u_int32_t	sv_handler;
1469	int		sv_mask;
1470	int		sv_flags;
1471};
1472
1473int
1474ofreebsd32_sigvec(struct thread *td,
1475			  struct ofreebsd32_sigvec_args *uap)
1476{
1477	struct sigvec32 vec;
1478	struct sigaction sa, osa, *sap;
1479	int error;
1480
1481	if (uap->signum <= 0 || uap->signum >= ONSIG)
1482		return (EINVAL);
1483
1484	if (uap->nsv) {
1485		error = copyin(uap->nsv, &vec, sizeof(vec));
1486		if (error)
1487			return (error);
1488		sa.sa_handler = PTRIN(vec.sv_handler);
1489		OSIG2SIG(vec.sv_mask, sa.sa_mask);
1490		sa.sa_flags = vec.sv_flags;
1491		sa.sa_flags ^= SA_RESTART;
1492		sap = &sa;
1493	} else
1494		sap = NULL;
1495	error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
1496	if (error == 0 && uap->osv != NULL) {
1497		vec.sv_handler = PTROUT(osa.sa_handler);
1498		SIG2OSIG(osa.sa_mask, vec.sv_mask);
1499		vec.sv_flags = osa.sa_flags;
1500		vec.sv_flags &= ~SA_NOCLDWAIT;
1501		vec.sv_flags ^= SA_RESTART;
1502		error = copyout(&vec, uap->osv, sizeof(vec));
1503	}
1504	return (error);
1505}
1506
1507int
1508ofreebsd32_sigblock(struct thread *td,
1509			    struct ofreebsd32_sigblock_args *uap)
1510{
1511	struct proc *p = td->td_proc;
1512	sigset_t set;
1513
1514	OSIG2SIG(uap->mask, set);
1515	SIG_CANTMASK(set);
1516	PROC_LOCK(p);
1517	SIG2OSIG(td->td_sigmask, td->td_retval[0]);
1518	SIGSETOR(td->td_sigmask, set);
1519	PROC_UNLOCK(p);
1520	return (0);
1521}
1522
1523int
1524ofreebsd32_sigsetmask(struct thread *td,
1525			      struct ofreebsd32_sigsetmask_args *uap)
1526{
1527	struct proc *p = td->td_proc;
1528	sigset_t set;
1529
1530	OSIG2SIG(uap->mask, set);
1531	SIG_CANTMASK(set);
1532	PROC_LOCK(p);
1533	SIG2OSIG(td->td_sigmask, td->td_retval[0]);
1534	SIGSETLO(td->td_sigmask, set);
1535	signotify(td);
1536	PROC_UNLOCK(p);
1537	return (0);
1538}
1539
1540int
1541ofreebsd32_sigsuspend(struct thread *td,
1542			      struct ofreebsd32_sigsuspend_args *uap)
1543{
1544	struct proc *p = td->td_proc;
1545	sigset_t mask;
1546
1547	PROC_LOCK(p);
1548	td->td_oldsigmask = td->td_sigmask;
1549	td->td_pflags |= TDP_OLDMASK;
1550	OSIG2SIG(uap->mask, mask);
1551	SIG_CANTMASK(mask);
1552	SIGSETLO(td->td_sigmask, mask);
1553	signotify(td);
1554	while (msleep(&p->p_sigacts, &p->p_mtx, PPAUSE|PCATCH, "opause", 0) == 0)
1555		/* void */;
1556	PROC_UNLOCK(p);
1557	/* always return EINTR rather than ERESTART... */
1558	return (EINTR);
1559}
1560
1561struct sigstack32 {
1562	u_int32_t	ss_sp;
1563	int		ss_onstack;
1564};
1565
1566int
1567ofreebsd32_sigstack(struct thread *td,
1568			    struct ofreebsd32_sigstack_args *uap)
1569{
1570	struct sigstack32 s32;
1571	struct sigstack nss, oss;
1572	int error = 0;
1573
1574	if (uap->nss != NULL) {
1575		error = copyin(uap->nss, &s32, sizeof(s32));
1576		if (error)
1577			return (error);
1578		nss.ss_sp = PTRIN(s32.ss_sp);
1579		CP(s32, nss, ss_onstack);
1580	}
1581	oss.ss_sp = td->td_sigstk.ss_sp;
1582	oss.ss_onstack = sigonstack(cpu_getstack(td));
1583	if (uap->nss != NULL) {
1584		td->td_sigstk.ss_sp = nss.ss_sp;
1585		td->td_sigstk.ss_size = 0;
1586		td->td_sigstk.ss_flags |= nss.ss_onstack & SS_ONSTACK;
1587		td->td_pflags |= TDP_ALTSTACK;
1588	}
1589	if (uap->oss != NULL) {
1590		s32.ss_sp = PTROUT(oss.ss_sp);
1591		CP(oss, s32, ss_onstack);
1592		error = copyout(&s32, uap->oss, sizeof(s32));
1593	}
1594	return (error);
1595}
1596#endif
1597
1598int
1599freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
1600{
1601	struct timespec32 rmt32, rqt32;
1602	struct timespec rmt, rqt;
1603	int error;
1604
1605	error = copyin(uap->rqtp, &rqt32, sizeof(rqt32));
1606	if (error)
1607		return (error);
1608
1609	CP(rqt32, rqt, tv_sec);
1610	CP(rqt32, rqt, tv_nsec);
1611
1612	if (uap->rmtp &&
1613	    !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
1614		return (EFAULT);
1615	error = kern_nanosleep(td, &rqt, &rmt);
1616	if (error && uap->rmtp) {
1617		int error2;
1618
1619		CP(rmt, rmt32, tv_sec);
1620		CP(rmt, rmt32, tv_nsec);
1621
1622		error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt32));
1623		if (error2)
1624			error = error2;
1625	}
1626	return (error);
1627}
1628
1629int
1630freebsd32_clock_gettime(struct thread *td,
1631			struct freebsd32_clock_gettime_args *uap)
1632{
1633	struct timespec	ats;
1634	struct timespec32 ats32;
1635	int error;
1636
1637	error = kern_clock_gettime(td, uap->clock_id, &ats);
1638	if (error == 0) {
1639		CP(ats, ats32, tv_sec);
1640		CP(ats, ats32, tv_nsec);
1641		error = copyout(&ats32, uap->tp, sizeof(ats32));
1642	}
1643	return (error);
1644}
1645
1646int
1647freebsd32_clock_settime(struct thread *td,
1648			struct freebsd32_clock_settime_args *uap)
1649{
1650	struct timespec	ats;
1651	struct timespec32 ats32;
1652	int error;
1653
1654	error = copyin(uap->tp, &ats32, sizeof(ats32));
1655	if (error)
1656		return (error);
1657	CP(ats32, ats, tv_sec);
1658	CP(ats32, ats, tv_nsec);
1659
1660	return (kern_clock_settime(td, uap->clock_id, &ats));
1661}
1662
1663int
1664freebsd32_clock_getres(struct thread *td,
1665		       struct freebsd32_clock_getres_args *uap)
1666{
1667	struct timespec	ts;
1668	struct timespec32 ts32;
1669	int error;
1670
1671	if (uap->tp == NULL)
1672		return (0);
1673	error = kern_clock_getres(td, uap->clock_id, &ts);
1674	if (error == 0) {
1675		CP(ts, ts32, tv_sec);
1676		CP(ts, ts32, tv_nsec);
1677		error = copyout(&ts32, uap->tp, sizeof(ts32));
1678	}
1679	return (error);
1680}
1681
1682#if 0
1683
1684int
1685freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
1686{
1687	int error;
1688	struct yyy32 *p32, s32;
1689	struct yyy *p = NULL, s;
1690
1691	if (uap->zzz) {
1692		error = copyin(uap->zzz, &s32, sizeof(s32));
1693		if (error)
1694			return (error);
1695		/* translate in */
1696		p = &s;
1697	}
1698	error = kern_xxx(td, p);
1699	if (error)
1700		return (error);
1701	if (uap->zzz) {
1702		/* translate out */
1703		error = copyout(&s32, p32, sizeof(s32));
1704	}
1705	return (error);
1706}
1707
1708#endif
1709