freebsd32_misc.c revision 205014
1100384Speter/*-
2100384Speter * Copyright (c) 2002 Doug Rabson
3100384Speter * All rights reserved.
4100384Speter *
5100384Speter * Redistribution and use in source and binary forms, with or without
6100384Speter * modification, are permitted provided that the following conditions
7100384Speter * are met:
8100384Speter * 1. Redistributions of source code must retain the above copyright
9100384Speter *    notice, this list of conditions and the following disclaimer.
10100384Speter * 2. Redistributions in binary form must reproduce the above copyright
11100384Speter *    notice, this list of conditions and the following disclaimer in the
12100384Speter *    documentation and/or other materials provided with the distribution.
13100384Speter *
14100384Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15100384Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16100384Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17100384Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18100384Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19100384Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20100384Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21100384Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22100384Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23100384Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24100384Speter * SUCH DAMAGE.
25100384Speter */
26100384Speter
27118031Sobrien#include <sys/cdefs.h>
28118031Sobrien__FBSDID("$FreeBSD: head/sys/compat/freebsd32/freebsd32_misc.c 205014 2010-03-11 14:49:06Z nwhitehorn $");
29118031Sobrien
30104738Speter#include "opt_compat.h"
31191673Sjamie#include "opt_inet.h"
32191673Sjamie#include "opt_inet6.h"
33104738Speter
34205014Snwhitehorn#define __ELF_WORD_SIZE 32
35205014Snwhitehorn
36100384Speter#include <sys/param.h>
37100384Speter#include <sys/bus.h>
38162954Sphk#include <sys/clock.h>
39100384Speter#include <sys/exec.h>
40100384Speter#include <sys/fcntl.h>
41100384Speter#include <sys/filedesc.h>
42100384Speter#include <sys/imgact.h>
43185435Sbz#include <sys/jail.h>
44100384Speter#include <sys/kernel.h>
45161343Sjkim#include <sys/limits.h>
46100384Speter#include <sys/lock.h>
47100384Speter#include <sys/malloc.h>
48100384Speter#include <sys/file.h>		/* Must come after sys/malloc.h */
49205014Snwhitehorn#include <sys/imgact.h>
50151909Sps#include <sys/mbuf.h>
51100384Speter#include <sys/mman.h>
52100384Speter#include <sys/module.h>
53100384Speter#include <sys/mount.h>
54100384Speter#include <sys/mutex.h>
55183044Sobrien#include <sys/namei.h>
56100384Speter#include <sys/proc.h>
57100384Speter#include <sys/reboot.h>
58100384Speter#include <sys/resource.h>
59100384Speter#include <sys/resourcevar.h>
60100384Speter#include <sys/selinfo.h>
61146950Sps#include <sys/eventvar.h>	/* Must come after sys/selinfo.h */
62100384Speter#include <sys/pipe.h>		/* Must come after sys/selinfo.h */
63100384Speter#include <sys/signal.h>
64100384Speter#include <sys/signalvar.h>
65100384Speter#include <sys/socket.h>
66100384Speter#include <sys/socketvar.h>
67100384Speter#include <sys/stat.h>
68150883Sjhb#include <sys/syscall.h>
69113859Sjhb#include <sys/syscallsubr.h>
70100384Speter#include <sys/sysctl.h>
71100384Speter#include <sys/sysent.h>
72100384Speter#include <sys/sysproto.h>
73183044Sobrien#include <sys/systm.h>
74162551Sdavidxu#include <sys/thr.h>
75100384Speter#include <sys/unistd.h>
76162551Sdavidxu#include <sys/ucontext.h>
77100384Speter#include <sys/vnode.h>
78127140Sjhb#include <sys/wait.h>
79157285Sps#include <sys/ipc.h>
80174381Sjhb#include <sys/msg.h>
81174381Sjhb#include <sys/sem.h>
82157285Sps#include <sys/shm.h>
83100384Speter
84191673Sjamie#ifdef INET
85191673Sjamie#include <netinet/in.h>
86191673Sjamie#endif
87191673Sjamie
88100384Speter#include <vm/vm.h>
89100384Speter#include <vm/vm_kern.h>
90100384Speter#include <vm/vm_param.h>
91100384Speter#include <vm/pmap.h>
92100384Speter#include <vm/vm_map.h>
93100384Speter#include <vm/vm_object.h>
94100384Speter#include <vm/vm_extern.h>
95100384Speter
96151582Sps#include <machine/cpu.h>
97205014Snwhitehorn#include <machine/elf.h>
98151582Sps
99183188Sobrien#include <security/audit/audit.h>
100183188Sobrien
101119333Speter#include <compat/freebsd32/freebsd32_util.h>
102119333Speter#include <compat/freebsd32/freebsd32.h>
103174380Sjhb#include <compat/freebsd32/freebsd32_ipc.h>
104163018Sdavidxu#include <compat/freebsd32/freebsd32_signal.h>
105119333Speter#include <compat/freebsd32/freebsd32_proto.h>
106100384Speter
107121719SpeterCTASSERT(sizeof(struct timeval32) == 8);
108121719SpeterCTASSERT(sizeof(struct timespec32) == 8);
109174377SjhbCTASSERT(sizeof(struct itimerval32) == 16);
110121719SpeterCTASSERT(sizeof(struct statfs32) == 256);
111121719SpeterCTASSERT(sizeof(struct rusage32) == 72);
112174377SjhbCTASSERT(sizeof(struct sigaltstack32) == 12);
113174377SjhbCTASSERT(sizeof(struct kevent32) == 20);
114174377SjhbCTASSERT(sizeof(struct iovec32) == 8);
115174377SjhbCTASSERT(sizeof(struct msghdr32) == 28);
116174377SjhbCTASSERT(sizeof(struct stat32) == 96);
117174377SjhbCTASSERT(sizeof(struct sigaction32) == 24);
118121719Speter
119174377Sjhbstatic int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);
120174377Sjhbstatic int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count);
121174377Sjhb
122205014Snwhitehorn#if BYTE_ORDER == BIG_ENDIAN
123205014Snwhitehorn#define PAIR32TO64(type, name) ((name ## 2) | ((type)(name ## 1) << 32))
124205014Snwhitehorn#define RETVAL_HI 0
125205014Snwhitehorn#define RETVAL_LO 1
126205014Snwhitehorn#else
127205014Snwhitehorn#define PAIR32TO64(type, name) ((name ## 1) | ((type)(name ## 2) << 32))
128205014Snwhitehorn#define RETVAL_HI 1
129205014Snwhitehorn#define RETVAL_LO 0
130205014Snwhitehorn#endif
131205014Snwhitehorn
132100384Speterint
133119333Speterfreebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
134100384Speter{
135127140Sjhb	int error, status;
136127140Sjhb	struct rusage32 ru32;
137136152Sjhb	struct rusage ru, *rup;
138100384Speter
139136152Sjhb	if (uap->rusage != NULL)
140136152Sjhb		rup = &ru;
141136152Sjhb	else
142136152Sjhb		rup = NULL;
143136152Sjhb	error = kern_wait(td, uap->pid, &status, uap->options, rup);
144100384Speter	if (error)
145100384Speter		return (error);
146127140Sjhb	if (uap->status != NULL)
147127140Sjhb		error = copyout(&status, uap->status, sizeof(status));
148127140Sjhb	if (uap->rusage != NULL && error == 0) {
149100384Speter		TV_CP(ru, ru32, ru_utime);
150100384Speter		TV_CP(ru, ru32, ru_stime);
151100384Speter		CP(ru, ru32, ru_maxrss);
152100384Speter		CP(ru, ru32, ru_ixrss);
153100384Speter		CP(ru, ru32, ru_idrss);
154100384Speter		CP(ru, ru32, ru_isrss);
155100384Speter		CP(ru, ru32, ru_minflt);
156100384Speter		CP(ru, ru32, ru_majflt);
157100384Speter		CP(ru, ru32, ru_nswap);
158100384Speter		CP(ru, ru32, ru_inblock);
159100384Speter		CP(ru, ru32, ru_oublock);
160100384Speter		CP(ru, ru32, ru_msgsnd);
161100384Speter		CP(ru, ru32, ru_msgrcv);
162100384Speter		CP(ru, ru32, ru_nsignals);
163100384Speter		CP(ru, ru32, ru_nvcsw);
164100384Speter		CP(ru, ru32, ru_nivcsw);
165127140Sjhb		error = copyout(&ru32, uap->rusage, sizeof(ru32));
166100384Speter	}
167100384Speter	return (error);
168100384Speter}
169100384Speter
170128597Smarcel#ifdef COMPAT_FREEBSD4
171174526Sjhbstatic void
172100384Spetercopy_statfs(struct statfs *in, struct statfs32 *out)
173100384Speter{
174172003Sjhb
175174424Sscottl	statfs_scale_blocks(in, INT32_MAX);
176156266Sps	bzero(out, sizeof(*out));
177100384Speter	CP(*in, *out, f_bsize);
178172003Sjhb	out->f_iosize = MIN(in->f_iosize, INT32_MAX);
179100384Speter	CP(*in, *out, f_blocks);
180100384Speter	CP(*in, *out, f_bfree);
181100384Speter	CP(*in, *out, f_bavail);
182172003Sjhb	out->f_files = MIN(in->f_files, INT32_MAX);
183174526Sjhb	out->f_ffree = MIN(in->f_ffree, INT32_MAX);
184100384Speter	CP(*in, *out, f_fsid);
185100384Speter	CP(*in, *out, f_owner);
186100384Speter	CP(*in, *out, f_type);
187100384Speter	CP(*in, *out, f_flags);
188174526Sjhb	out->f_syncwrites = MIN(in->f_syncwrites, INT32_MAX);
189174526Sjhb	out->f_asyncwrites = MIN(in->f_asyncwrites, INT32_MAX);
190156266Sps	strlcpy(out->f_fstypename,
191156266Sps	      in->f_fstypename, MFSNAMELEN);
192156266Sps	strlcpy(out->f_mntonname,
193156266Sps	      in->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN));
194174526Sjhb	out->f_syncreads = MIN(in->f_syncreads, INT32_MAX);
195174526Sjhb	out->f_asyncreads = MIN(in->f_asyncreads, INT32_MAX);
196156266Sps	strlcpy(out->f_mntfromname,
197156266Sps	      in->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN));
198100384Speter}
199128597Smarcel#endif
200100384Speter
201128597Smarcel#ifdef COMPAT_FREEBSD4
202100384Speterint
203128260Speterfreebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap)
204100384Speter{
205147178Spjd	struct statfs *buf, *sp;
206147178Spjd	struct statfs32 stat32;
207147178Spjd	size_t count, size;
208100384Speter	int error;
209100384Speter
210147178Spjd	count = uap->bufsize / sizeof(struct statfs32);
211147178Spjd	size = count * sizeof(struct statfs);
212147302Spjd	error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags);
213147302Spjd	if (size > 0) {
214100384Speter		count = td->td_retval[0];
215147178Spjd		sp = buf;
216147178Spjd		while (count > 0 && error == 0) {
217174526Sjhb			copy_statfs(sp, &stat32);
218147178Spjd			error = copyout(&stat32, uap->buf, sizeof(stat32));
219147178Spjd			sp++;
220147178Spjd			uap->buf++;
221147178Spjd			count--;
222100384Speter		}
223147178Spjd		free(buf, M_TEMP);
224100384Speter	}
225100384Speter	return (error);
226100384Speter}
227128597Smarcel#endif
228100384Speter
229100384Speterint
230119333Speterfreebsd32_sigaltstack(struct thread *td,
231119333Speter		      struct freebsd32_sigaltstack_args *uap)
232100384Speter{
233113859Sjhb	struct sigaltstack32 s32;
234113859Sjhb	struct sigaltstack ss, oss, *ssp;
235100384Speter	int error;
236100384Speter
237113859Sjhb	if (uap->ss != NULL) {
238113859Sjhb		error = copyin(uap->ss, &s32, sizeof(s32));
239100384Speter		if (error)
240100384Speter			return (error);
241113859Sjhb		PTRIN_CP(s32, ss, ss_sp);
242113859Sjhb		CP(s32, ss, ss_size);
243113859Sjhb		CP(s32, ss, ss_flags);
244113859Sjhb		ssp = &ss;
245113859Sjhb	} else
246113859Sjhb		ssp = NULL;
247113859Sjhb	error = kern_sigaltstack(td, ssp, &oss);
248113859Sjhb	if (error == 0 && uap->oss != NULL) {
249113859Sjhb		PTROUT_CP(oss, s32, ss_sp);
250113859Sjhb		CP(oss, s32, ss_size);
251113859Sjhb		CP(oss, s32, ss_flags);
252113859Sjhb		error = copyout(&s32, uap->oss, sizeof(s32));
253100384Speter	}
254100384Speter	return (error);
255100384Speter}
256100384Speter
257142059Sjhb/*
258142059Sjhb * Custom version of exec_copyin_args() so that we can translate
259142059Sjhb * the pointers.
260142059Sjhb */
261142059Sjhbstatic int
262142059Sjhbfreebsd32_exec_copyin_args(struct image_args *args, char *fname,
263142059Sjhb    enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv)
264100384Speter{
265142059Sjhb	char *argp, *envp;
266142059Sjhb	u_int32_t *p32, arg;
267142059Sjhb	size_t length;
268100384Speter	int error;
269100384Speter
270142059Sjhb	bzero(args, sizeof(*args));
271142059Sjhb	if (argv == NULL)
272142059Sjhb		return (EFAULT);
273100384Speter
274142059Sjhb	/*
275142059Sjhb	 * Allocate temporary demand zeroed space for argument and
276142059Sjhb	 *	environment strings
277142059Sjhb	 */
278147588Sjhb	args->buf = (char *) kmem_alloc_wait(exec_map,
279147588Sjhb	    PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
280142059Sjhb	if (args->buf == NULL)
281142059Sjhb		return (ENOMEM);
282142059Sjhb	args->begin_argv = args->buf;
283142059Sjhb	args->endp = args->begin_argv;
284142059Sjhb	args->stringspace = ARG_MAX;
285142059Sjhb
286142059Sjhb	/*
287142059Sjhb	 * Copy the file name.
288142059Sjhb	 */
289177789Skib	if (fname != NULL) {
290177789Skib		args->fname = args->buf + ARG_MAX;
291177789Skib		error = (segflg == UIO_SYSSPACE) ?
292177789Skib		    copystr(fname, args->fname, PATH_MAX, &length) :
293177789Skib		    copyinstr(fname, args->fname, PATH_MAX, &length);
294177789Skib		if (error != 0)
295177789Skib			goto err_exit;
296177789Skib	} else
297177789Skib		args->fname = NULL;
298142059Sjhb
299142059Sjhb	/*
300142059Sjhb	 * extract arguments first
301142059Sjhb	 */
302142059Sjhb	p32 = argv;
303142059Sjhb	for (;;) {
304142059Sjhb		error = copyin(p32++, &arg, sizeof(arg));
305142059Sjhb		if (error)
306156440Sups			goto err_exit;
307142059Sjhb		if (arg == 0)
308142059Sjhb			break;
309142059Sjhb		argp = PTRIN(arg);
310142059Sjhb		error = copyinstr(argp, args->endp, args->stringspace, &length);
311142059Sjhb		if (error) {
312142059Sjhb			if (error == ENAMETOOLONG)
313156440Sups				error = E2BIG;
314156440Sups			goto err_exit;
315142059Sjhb		}
316142059Sjhb		args->stringspace -= length;
317142059Sjhb		args->endp += length;
318142059Sjhb		args->argc++;
319100384Speter	}
320142059Sjhb
321142059Sjhb	args->begin_envv = args->endp;
322142059Sjhb
323142059Sjhb	/*
324142059Sjhb	 * extract environment strings
325142059Sjhb	 */
326142059Sjhb	if (envv) {
327142059Sjhb		p32 = envv;
328142059Sjhb		for (;;) {
329100384Speter			error = copyin(p32++, &arg, sizeof(arg));
330100384Speter			if (error)
331156440Sups				goto err_exit;
332142059Sjhb			if (arg == 0)
333142059Sjhb				break;
334142059Sjhb			envp = PTRIN(arg);
335142059Sjhb			error = copyinstr(envp, args->endp, args->stringspace,
336142059Sjhb			    &length);
337142059Sjhb			if (error) {
338142059Sjhb				if (error == ENAMETOOLONG)
339156440Sups					error = E2BIG;
340156440Sups				goto err_exit;
341142059Sjhb			}
342142059Sjhb			args->stringspace -= length;
343142059Sjhb			args->endp += length;
344142059Sjhb			args->envc++;
345142059Sjhb		}
346100384Speter	}
347100384Speter
348142059Sjhb	return (0);
349156440Sups
350156440Supserr_exit:
351156440Sups	kmem_free_wakeup(exec_map, (vm_offset_t)args->buf,
352156440Sups	    PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
353156440Sups	args->buf = NULL;
354156440Sups	return (error);
355100384Speter}
356100384Speter
357142059Sjhbint
358142059Sjhbfreebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
359142059Sjhb{
360142059Sjhb	struct image_args eargs;
361142059Sjhb	int error;
362142059Sjhb
363142059Sjhb	error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE,
364142059Sjhb	    uap->argv, uap->envv);
365142059Sjhb	if (error == 0)
366142059Sjhb		error = kern_execve(td, &eargs, NULL);
367142059Sjhb	return (error);
368142059Sjhb}
369142059Sjhb
370177789Skibint
371177789Skibfreebsd32_fexecve(struct thread *td, struct freebsd32_fexecve_args *uap)
372177789Skib{
373177789Skib	struct image_args eargs;
374177789Skib	int error;
375177789Skib
376177789Skib	error = freebsd32_exec_copyin_args(&eargs, NULL, UIO_SYSSPACE,
377177789Skib	    uap->argv, uap->envv);
378177789Skib	if (error == 0) {
379177789Skib		eargs.fd = uap->fd;
380177789Skib		error = kern_execve(td, &eargs, NULL);
381177789Skib	}
382177789Skib	return (error);
383177789Skib}
384177789Skib
385114987Speter#ifdef __ia64__
386100384Speterstatic int
387119333Speterfreebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
388119333Speter		       int prot, int fd, off_t pos)
389100384Speter{
390100384Speter	vm_map_t map;
391100384Speter	vm_map_entry_t entry;
392100384Speter	int rv;
393100384Speter
394100384Speter	map = &td->td_proc->p_vmspace->vm_map;
395100384Speter	if (fd != -1)
396100384Speter		prot |= VM_PROT_WRITE;
397100384Speter
398100384Speter	if (vm_map_lookup_entry(map, start, &entry)) {
399100384Speter		if ((entry->protection & prot) != prot) {
400100384Speter			rv = vm_map_protect(map,
401100384Speter					    trunc_page(start),
402100384Speter					    round_page(end),
403100384Speter					    entry->protection | prot,
404100384Speter					    FALSE);
405100384Speter			if (rv != KERN_SUCCESS)
406100384Speter				return (EINVAL);
407100384Speter		}
408100384Speter	} else {
409100384Speter		vm_offset_t addr = trunc_page(start);
410100384Speter		rv = vm_map_find(map, 0, 0,
411100384Speter				 &addr, PAGE_SIZE, FALSE, prot,
412100384Speter				 VM_PROT_ALL, 0);
413100384Speter		if (rv != KERN_SUCCESS)
414100384Speter			return (EINVAL);
415100384Speter	}
416100384Speter
417100384Speter	if (fd != -1) {
418100384Speter		struct pread_args r;
419107849Salfred		r.fd = fd;
420107849Salfred		r.buf = (void *) start;
421107849Salfred		r.nbyte = end - start;
422107849Salfred		r.offset = pos;
423100384Speter		return (pread(td, &r));
424100384Speter	} else {
425100384Speter		while (start < end) {
426100384Speter			subyte((void *) start, 0);
427100384Speter			start++;
428100384Speter		}
429100384Speter		return (0);
430100384Speter	}
431100384Speter}
432114987Speter#endif
433100384Speter
434100384Speterint
435119333Speterfreebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
436100384Speter{
437100384Speter	struct mmap_args ap;
438107849Salfred	vm_offset_t addr = (vm_offset_t) uap->addr;
439107849Salfred	vm_size_t len	 = uap->len;
440107849Salfred	int prot	 = uap->prot;
441107849Salfred	int flags	 = uap->flags;
442107849Salfred	int fd		 = uap->fd;
443205014Snwhitehorn	off_t pos	 = PAIR32TO64(off_t,uap->pos);
444114987Speter#ifdef __ia64__
445100384Speter	vm_size_t pageoff;
446100384Speter	int error;
447100384Speter
448100384Speter	/*
449100384Speter	 * Attempt to handle page size hassles.
450100384Speter	 */
451100384Speter	pageoff = (pos & PAGE_MASK);
452100384Speter	if (flags & MAP_FIXED) {
453100384Speter		vm_offset_t start, end;
454100384Speter		start = addr;
455100384Speter		end = addr + len;
456100384Speter
457100384Speter		if (start != trunc_page(start)) {
458119333Speter			error = freebsd32_mmap_partial(td, start,
459119333Speter						       round_page(start), prot,
460119333Speter						       fd, pos);
461100384Speter			if (fd != -1)
462100384Speter				pos += round_page(start) - start;
463100384Speter			start = round_page(start);
464100384Speter		}
465100384Speter		if (end != round_page(end)) {
466100384Speter			vm_offset_t t = trunc_page(end);
467119333Speter			error = freebsd32_mmap_partial(td, t, end,
468100384Speter						  prot, fd,
469100384Speter						  pos + t - start);
470100384Speter			end = trunc_page(end);
471100384Speter		}
472100384Speter		if (end > start && fd != -1 && (pos & PAGE_MASK)) {
473100384Speter			/*
474100384Speter			 * We can't map this region at all. The specified
475100384Speter			 * address doesn't have the same alignment as the file
476100384Speter			 * position. Fake the mapping by simply reading the
477100384Speter			 * entire region into memory. First we need to make
478100384Speter			 * sure the region exists.
479100384Speter			 */
480100384Speter			vm_map_t map;
481100384Speter			struct pread_args r;
482100384Speter			int rv;
483100384Speter
484100384Speter			prot |= VM_PROT_WRITE;
485100384Speter			map = &td->td_proc->p_vmspace->vm_map;
486100384Speter			rv = vm_map_remove(map, start, end);
487169181Salc			if (rv != KERN_SUCCESS)
488100384Speter				return (EINVAL);
489100384Speter			rv = vm_map_find(map, 0, 0,
490100384Speter					 &start, end - start, FALSE,
491100384Speter					 prot, VM_PROT_ALL, 0);
492100384Speter			if (rv != KERN_SUCCESS)
493100384Speter				return (EINVAL);
494107849Salfred			r.fd = fd;
495107849Salfred			r.buf = (void *) start;
496107849Salfred			r.nbyte = end - start;
497107849Salfred			r.offset = pos;
498100384Speter			error = pread(td, &r);
499100384Speter			if (error)
500100384Speter				return (error);
501100384Speter
502100384Speter			td->td_retval[0] = addr;
503100384Speter			return (0);
504100384Speter		}
505100384Speter		if (end == start) {
506100384Speter			/*
507100384Speter			 * After dealing with the ragged ends, there
508100384Speter			 * might be none left.
509100384Speter			 */
510100384Speter			td->td_retval[0] = addr;
511100384Speter			return (0);
512100384Speter		}
513100384Speter		addr = start;
514100384Speter		len = end - start;
515100384Speter	}
516114987Speter#endif
517100384Speter
518107849Salfred	ap.addr = (void *) addr;
519107849Salfred	ap.len = len;
520107849Salfred	ap.prot = prot;
521107849Salfred	ap.flags = flags;
522107849Salfred	ap.fd = fd;
523107849Salfred	ap.pos = pos;
524100384Speter
525100384Speter	return (mmap(td, &ap));
526100384Speter}
527100384Speter
528171215Speter#ifdef COMPAT_FREEBSD6
529171215Speterint
530171215Speterfreebsd6_freebsd32_mmap(struct thread *td, struct freebsd6_freebsd32_mmap_args *uap)
531171215Speter{
532171215Speter	struct freebsd32_mmap_args ap;
533171215Speter
534171215Speter	ap.addr = uap->addr;
535171215Speter	ap.len = uap->len;
536171215Speter	ap.prot = uap->prot;
537171215Speter	ap.flags = uap->flags;
538171215Speter	ap.fd = uap->fd;
539205014Snwhitehorn	ap.pos1 = uap->pos1;
540205014Snwhitehorn	ap.pos2 = uap->pos2;
541171215Speter
542171215Speter	return (freebsd32_mmap(td, &ap));
543171215Speter}
544171215Speter#endif
545171215Speter
546100384Speterint
547119333Speterfreebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
548100384Speter{
549142059Sjhb	struct itimerval itv, oitv, *itvp;
550142059Sjhb	struct itimerval32 i32;
551100384Speter	int error;
552100384Speter
553142059Sjhb	if (uap->itv != NULL) {
554142059Sjhb		error = copyin(uap->itv, &i32, sizeof(i32));
555100384Speter		if (error)
556100384Speter			return (error);
557142059Sjhb		TV_CP(i32, itv, it_interval);
558142059Sjhb		TV_CP(i32, itv, it_value);
559142059Sjhb		itvp = &itv;
560142059Sjhb	} else
561142059Sjhb		itvp = NULL;
562142059Sjhb	error = kern_setitimer(td, uap->which, itvp, &oitv);
563142059Sjhb	if (error || uap->oitv == NULL)
564100384Speter		return (error);
565142059Sjhb	TV_CP(oitv, i32, it_interval);
566142059Sjhb	TV_CP(oitv, i32, it_value);
567142059Sjhb	return (copyout(&i32, uap->oitv, sizeof(i32)));
568100384Speter}
569100384Speter
570100384Speterint
571125171Speterfreebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)
572125171Speter{
573142059Sjhb	struct itimerval itv;
574142059Sjhb	struct itimerval32 i32;
575125171Speter	int error;
576125171Speter
577142059Sjhb	error = kern_getitimer(td, uap->which, &itv);
578142059Sjhb	if (error || uap->itv == NULL)
579125171Speter		return (error);
580142059Sjhb	TV_CP(itv, i32, it_interval);
581142059Sjhb	TV_CP(itv, i32, it_value);
582142059Sjhb	return (copyout(&i32, uap->itv, sizeof(i32)));
583125171Speter}
584125171Speter
585125171Speterint
586119333Speterfreebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
587100384Speter{
588142059Sjhb	struct timeval32 tv32;
589142059Sjhb	struct timeval tv, *tvp;
590100384Speter	int error;
591100384Speter
592142059Sjhb	if (uap->tv != NULL) {
593142059Sjhb		error = copyin(uap->tv, &tv32, sizeof(tv32));
594100384Speter		if (error)
595100384Speter			return (error);
596142059Sjhb		CP(tv32, tv, tv_sec);
597142059Sjhb		CP(tv32, tv, tv_usec);
598142059Sjhb		tvp = &tv;
599142059Sjhb	} else
600142059Sjhb		tvp = NULL;
601100384Speter	/*
602142059Sjhb	 * XXX Do pointers need PTRIN()?
603100384Speter	 */
604197049Skib	return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp,
605197049Skib	    sizeof(int32_t) * 8));
606100384Speter}
607100384Speter
608198508Skibint
609198508Skibfreebsd32_pselect(struct thread *td, struct freebsd32_pselect_args *uap)
610198508Skib{
611198508Skib	struct timespec32 ts32;
612198508Skib	struct timespec ts;
613198508Skib	struct timeval tv, *tvp;
614198508Skib	sigset_t set, *uset;
615198508Skib	int error;
616198508Skib
617198508Skib	if (uap->ts != NULL) {
618198508Skib		error = copyin(uap->ts, &ts32, sizeof(ts32));
619198508Skib		if (error != 0)
620198508Skib			return (error);
621198508Skib		CP(ts32, ts, tv_sec);
622198508Skib		CP(ts32, ts, tv_nsec);
623198508Skib		TIMESPEC_TO_TIMEVAL(&tv, &ts);
624198508Skib		tvp = &tv;
625198508Skib	} else
626198508Skib		tvp = NULL;
627198508Skib	if (uap->sm != NULL) {
628198508Skib		error = copyin(uap->sm, &set, sizeof(set));
629198508Skib		if (error != 0)
630198508Skib			return (error);
631198508Skib		uset = &set;
632198508Skib	} else
633198508Skib		uset = NULL;
634198508Skib	/*
635198508Skib	 * XXX Do pointers need PTRIN()?
636198508Skib	 */
637198508Skib	error = kern_pselect(td, uap->nd, uap->in, uap->ou, uap->ex, tvp,
638198508Skib	    uset, sizeof(int32_t) * 8);
639198508Skib	return (error);
640198508Skib}
641198508Skib
642146950Sps/*
643146950Sps * Copy 'count' items into the destination list pointed to by uap->eventlist.
644146950Sps */
645146950Spsstatic int
646146950Spsfreebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count)
647146950Sps{
648146950Sps	struct freebsd32_kevent_args *uap;
649146950Sps	struct kevent32	ks32[KQ_NEVENTS];
650146950Sps	int i, error = 0;
651146950Sps
652146950Sps	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
653146950Sps	uap = (struct freebsd32_kevent_args *)arg;
654146950Sps
655146950Sps	for (i = 0; i < count; i++) {
656146950Sps		CP(kevp[i], ks32[i], ident);
657146950Sps		CP(kevp[i], ks32[i], filter);
658146950Sps		CP(kevp[i], ks32[i], flags);
659146950Sps		CP(kevp[i], ks32[i], fflags);
660146950Sps		CP(kevp[i], ks32[i], data);
661146950Sps		PTROUT_CP(kevp[i], ks32[i], udata);
662146950Sps	}
663146950Sps	error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
664146950Sps	if (error == 0)
665146950Sps		uap->eventlist += count;
666146950Sps	return (error);
667146950Sps}
668146950Sps
669146950Sps/*
670146950Sps * Copy 'count' items from the list pointed to by uap->changelist.
671146950Sps */
672146950Spsstatic int
673146950Spsfreebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)
674146950Sps{
675146950Sps	struct freebsd32_kevent_args *uap;
676146950Sps	struct kevent32	ks32[KQ_NEVENTS];
677146950Sps	int i, error = 0;
678146950Sps
679146950Sps	KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
680146950Sps	uap = (struct freebsd32_kevent_args *)arg;
681146950Sps
682146950Sps	error = copyin(uap->changelist, ks32, count * sizeof *ks32);
683146950Sps	if (error)
684146950Sps		goto done;
685146950Sps	uap->changelist += count;
686146950Sps
687146950Sps	for (i = 0; i < count; i++) {
688146950Sps		CP(ks32[i], kevp[i], ident);
689146950Sps		CP(ks32[i], kevp[i], filter);
690146950Sps		CP(ks32[i], kevp[i], flags);
691146950Sps		CP(ks32[i], kevp[i], fflags);
692146950Sps		CP(ks32[i], kevp[i], data);
693146950Sps		PTRIN_CP(ks32[i], kevp[i], udata);
694146950Sps	}
695146950Spsdone:
696146950Sps	return (error);
697146950Sps}
698146950Sps
699100384Speterint
700119333Speterfreebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
701114987Speter{
702114987Speter	struct timespec32 ts32;
703142934Sps	struct timespec ts, *tsp;
704146950Sps	struct kevent_copyops k_ops = { uap,
705146950Sps					freebsd32_kevent_copyout,
706146950Sps					freebsd32_kevent_copyin};
707146950Sps	int error;
708114987Speter
709114987Speter
710114987Speter	if (uap->timeout) {
711114987Speter		error = copyin(uap->timeout, &ts32, sizeof(ts32));
712114987Speter		if (error)
713114987Speter			return (error);
714114987Speter		CP(ts32, ts, tv_sec);
715114987Speter		CP(ts32, ts, tv_nsec);
716142934Sps		tsp = &ts;
717142934Sps	} else
718142934Sps		tsp = NULL;
719146950Sps	error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,
720146950Sps	    &k_ops, tsp);
721142934Sps	return (error);
722114987Speter}
723114987Speter
724114987Speterint
725119333Speterfreebsd32_gettimeofday(struct thread *td,
726119333Speter		       struct freebsd32_gettimeofday_args *uap)
727100384Speter{
728123425Speter	struct timeval atv;
729123425Speter	struct timeval32 atv32;
730123425Speter	struct timezone rtz;
731123425Speter	int error = 0;
732100384Speter
733123425Speter	if (uap->tp) {
734123425Speter		microtime(&atv);
735123425Speter		CP(atv, atv32, tv_sec);
736123425Speter		CP(atv, atv32, tv_usec);
737123425Speter		error = copyout(&atv32, uap->tp, sizeof (atv32));
738100384Speter	}
739123425Speter	if (error == 0 && uap->tzp != NULL) {
740123425Speter		rtz.tz_minuteswest = tz_minuteswest;
741123425Speter		rtz.tz_dsttime = tz_dsttime;
742123425Speter		error = copyout(&rtz, uap->tzp, sizeof (rtz));
743100384Speter	}
744100384Speter	return (error);
745100384Speter}
746100384Speter
747100384Speterint
748119333Speterfreebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
749100384Speter{
750136152Sjhb	struct rusage32 s32;
751136152Sjhb	struct rusage s;
752100384Speter	int error;
753100384Speter
754136152Sjhb	error = kern_getrusage(td, uap->who, &s);
755100384Speter	if (error)
756100384Speter		return (error);
757136152Sjhb	if (uap->rusage != NULL) {
758100384Speter		TV_CP(s, s32, ru_utime);
759100384Speter		TV_CP(s, s32, ru_stime);
760100384Speter		CP(s, s32, ru_maxrss);
761100384Speter		CP(s, s32, ru_ixrss);
762100384Speter		CP(s, s32, ru_idrss);
763100384Speter		CP(s, s32, ru_isrss);
764100384Speter		CP(s, s32, ru_minflt);
765100384Speter		CP(s, s32, ru_majflt);
766100384Speter		CP(s, s32, ru_nswap);
767100384Speter		CP(s, s32, ru_inblock);
768100384Speter		CP(s, s32, ru_oublock);
769100384Speter		CP(s, s32, ru_msgsnd);
770100384Speter		CP(s, s32, ru_msgrcv);
771100384Speter		CP(s, s32, ru_nsignals);
772100384Speter		CP(s, s32, ru_nvcsw);
773100384Speter		CP(s, s32, ru_nivcsw);
774136152Sjhb		error = copyout(&s32, uap->rusage, sizeof(s32));
775100384Speter	}
776100384Speter	return (error);
777100384Speter}
778100384Speter
779144450Sjhbstatic int
780144450Sjhbfreebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
781100384Speter{
782144450Sjhb	struct iovec32 iov32;
783144450Sjhb	struct iovec *iov;
784144450Sjhb	struct uio *uio;
785144450Sjhb	u_int iovlen;
786144450Sjhb	int error, i;
787100384Speter
788144450Sjhb	*uiop = NULL;
789144450Sjhb	if (iovcnt > UIO_MAXIOV)
790100384Speter		return (EINVAL);
791144450Sjhb	iovlen = iovcnt * sizeof(struct iovec);
792144450Sjhb	uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
793144450Sjhb	iov = (struct iovec *)(uio + 1);
794144450Sjhb	for (i = 0; i < iovcnt; i++) {
795144450Sjhb		error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
796144450Sjhb		if (error) {
797144450Sjhb			free(uio, M_IOV);
798144450Sjhb			return (error);
799144450Sjhb		}
800144450Sjhb		iov[i].iov_base = PTRIN(iov32.iov_base);
801144450Sjhb		iov[i].iov_len = iov32.iov_len;
802100384Speter	}
803144450Sjhb	uio->uio_iov = iov;
804144450Sjhb	uio->uio_iovcnt = iovcnt;
805144450Sjhb	uio->uio_segflg = UIO_USERSPACE;
806144450Sjhb	uio->uio_offset = -1;
807144450Sjhb	uio->uio_resid = 0;
808144450Sjhb	for (i = 0; i < iovcnt; i++) {
809144450Sjhb		if (iov->iov_len > INT_MAX - uio->uio_resid) {
810144450Sjhb			free(uio, M_IOV);
811144450Sjhb			return (EINVAL);
812144450Sjhb		}
813144450Sjhb		uio->uio_resid += iov->iov_len;
814144450Sjhb		iov++;
815144450Sjhb	}
816144450Sjhb	*uiop = uio;
817144450Sjhb	return (0);
818144450Sjhb}
819100384Speter
820144450Sjhbint
821144450Sjhbfreebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
822144450Sjhb{
823144450Sjhb	struct uio *auio;
824144450Sjhb	int error;
825100384Speter
826144450Sjhb	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
827144450Sjhb	if (error)
828144450Sjhb		return (error);
829144450Sjhb	error = kern_readv(td, uap->fd, auio);
830144450Sjhb	free(auio, M_IOV);
831100384Speter	return (error);
832100384Speter}
833100384Speter
834100384Speterint
835119333Speterfreebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
836100384Speter{
837144450Sjhb	struct uio *auio;
838144450Sjhb	int error;
839100384Speter
840144450Sjhb	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
841144450Sjhb	if (error)
842144450Sjhb		return (error);
843144450Sjhb	error = kern_writev(td, uap->fd, auio);
844144450Sjhb	free(auio, M_IOV);
845100384Speter	return (error);
846100384Speter}
847100384Speter
848100384Speterint
849147813Sjhbfreebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap)
850147813Sjhb{
851147813Sjhb	struct uio *auio;
852147813Sjhb	int error;
853147813Sjhb
854147813Sjhb	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
855147813Sjhb	if (error)
856147813Sjhb		return (error);
857205014Snwhitehorn	error = kern_preadv(td, uap->fd, auio, PAIR32TO64(off_t,uap->offset));
858147813Sjhb	free(auio, M_IOV);
859147813Sjhb	return (error);
860147813Sjhb}
861147813Sjhb
862147813Sjhbint
863147813Sjhbfreebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap)
864147813Sjhb{
865147813Sjhb	struct uio *auio;
866147813Sjhb	int error;
867147813Sjhb
868147813Sjhb	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
869147813Sjhb	if (error)
870147813Sjhb		return (error);
871205014Snwhitehorn	error = kern_pwritev(td, uap->fd, auio, PAIR32TO64(off_t,uap->offset));
872147813Sjhb	free(auio, M_IOV);
873147813Sjhb	return (error);
874147813Sjhb}
875147813Sjhb
876151359Spsstatic int
877151909Spsfreebsd32_copyiniov(struct iovec32 *iovp32, u_int iovcnt, struct iovec **iovp,
878151359Sps    int error)
879151359Sps{
880151359Sps	struct iovec32 iov32;
881151909Sps	struct iovec *iov;
882151909Sps	u_int iovlen;
883151359Sps	int i;
884151359Sps
885151909Sps	*iovp = NULL;
886151359Sps	if (iovcnt > UIO_MAXIOV)
887151359Sps		return (error);
888151359Sps	iovlen = iovcnt * sizeof(struct iovec);
889151909Sps	iov = malloc(iovlen, M_IOV, M_WAITOK);
890151359Sps	for (i = 0; i < iovcnt; i++) {
891151909Sps		error = copyin(&iovp32[i], &iov32, sizeof(struct iovec32));
892151359Sps		if (error) {
893151909Sps			free(iov, M_IOV);
894151359Sps			return (error);
895151359Sps		}
896151909Sps		iov[i].iov_base = PTRIN(iov32.iov_base);
897151909Sps		iov[i].iov_len = iov32.iov_len;
898151359Sps	}
899151909Sps	*iovp = iov;
900151359Sps	return (0);
901151359Sps}
902151359Sps
903151359Spsstatic int
904151359Spsfreebsd32_copyinmsghdr(struct msghdr32 *msg32, struct msghdr *msg)
905151359Sps{
906151359Sps	struct msghdr32 m32;
907151359Sps	int error;
908151359Sps
909151359Sps	error = copyin(msg32, &m32, sizeof(m32));
910151359Sps	if (error)
911151359Sps		return (error);
912151359Sps	msg->msg_name = PTRIN(m32.msg_name);
913151359Sps	msg->msg_namelen = m32.msg_namelen;
914151359Sps	msg->msg_iov = PTRIN(m32.msg_iov);
915151359Sps	msg->msg_iovlen = m32.msg_iovlen;
916151359Sps	msg->msg_control = PTRIN(m32.msg_control);
917151359Sps	msg->msg_controllen = m32.msg_controllen;
918151359Sps	msg->msg_flags = m32.msg_flags;
919151909Sps	return (0);
920151359Sps}
921151359Sps
922151359Spsstatic int
923151359Spsfreebsd32_copyoutmsghdr(struct msghdr *msg, struct msghdr32 *msg32)
924151359Sps{
925151359Sps	struct msghdr32 m32;
926151359Sps	int error;
927151359Sps
928151359Sps	m32.msg_name = PTROUT(msg->msg_name);
929151359Sps	m32.msg_namelen = msg->msg_namelen;
930151359Sps	m32.msg_iov = PTROUT(msg->msg_iov);
931151359Sps	m32.msg_iovlen = msg->msg_iovlen;
932151359Sps	m32.msg_control = PTROUT(msg->msg_control);
933151359Sps	m32.msg_controllen = msg->msg_controllen;
934151359Sps	m32.msg_flags = msg->msg_flags;
935151359Sps	error = copyout(&m32, msg32, sizeof(m32));
936151359Sps	return (error);
937151359Sps}
938151359Sps
939151909Sps#define FREEBSD32_ALIGNBYTES	(sizeof(int) - 1)
940151909Sps#define FREEBSD32_ALIGN(p)	\
941151909Sps	(((u_long)(p) + FREEBSD32_ALIGNBYTES) & ~FREEBSD32_ALIGNBYTES)
942151909Sps#define	FREEBSD32_CMSG_SPACE(l)	\
943151909Sps	(FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + FREEBSD32_ALIGN(l))
944151909Sps
945151909Sps#define	FREEBSD32_CMSG_DATA(cmsg)	((unsigned char *)(cmsg) + \
946151909Sps				 FREEBSD32_ALIGN(sizeof(struct cmsghdr)))
947151909Spsstatic int
948151909Spsfreebsd32_copy_msg_out(struct msghdr *msg, struct mbuf *control)
949151909Sps{
950151909Sps	struct cmsghdr *cm;
951151909Sps	void *data;
952151909Sps	socklen_t clen, datalen;
953151909Sps	int error;
954151909Sps	caddr_t ctlbuf;
955151909Sps	int len, maxlen, copylen;
956151909Sps	struct mbuf *m;
957151909Sps	error = 0;
958151909Sps
959151909Sps	len    = msg->msg_controllen;
960151909Sps	maxlen = msg->msg_controllen;
961151909Sps	msg->msg_controllen = 0;
962151909Sps
963151909Sps	m = control;
964151909Sps	ctlbuf = msg->msg_control;
965151909Sps
966151909Sps	while (m && len > 0) {
967151909Sps		cm = mtod(m, struct cmsghdr *);
968151909Sps		clen = m->m_len;
969151909Sps
970151909Sps		while (cm != NULL) {
971151909Sps
972151909Sps			if (sizeof(struct cmsghdr) > clen ||
973151909Sps			    cm->cmsg_len > clen) {
974151909Sps				error = EINVAL;
975151909Sps				break;
976151909Sps			}
977151909Sps
978151909Sps			data   = CMSG_DATA(cm);
979151909Sps			datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
980151909Sps
981151909Sps			/* Adjust message length */
982151909Sps			cm->cmsg_len = FREEBSD32_ALIGN(sizeof(struct cmsghdr)) +
983151909Sps			    datalen;
984151909Sps
985151909Sps
986151909Sps			/* Copy cmsghdr */
987151909Sps			copylen = sizeof(struct cmsghdr);
988151909Sps			if (len < copylen) {
989151909Sps				msg->msg_flags |= MSG_CTRUNC;
990151909Sps				copylen = len;
991151909Sps			}
992151909Sps
993151909Sps			error = copyout(cm,ctlbuf,copylen);
994151909Sps			if (error)
995151909Sps				goto exit;
996151909Sps
997151909Sps			ctlbuf += FREEBSD32_ALIGN(copylen);
998151909Sps			len    -= FREEBSD32_ALIGN(copylen);
999151909Sps
1000151909Sps			if (len <= 0)
1001151909Sps				break;
1002151909Sps
1003151909Sps			/* Copy data */
1004151909Sps			copylen = datalen;
1005151909Sps			if (len < copylen) {
1006151909Sps				msg->msg_flags |= MSG_CTRUNC;
1007151909Sps				copylen = len;
1008151909Sps			}
1009151909Sps
1010151909Sps			error = copyout(data,ctlbuf,copylen);
1011151909Sps			if (error)
1012151909Sps				goto exit;
1013151909Sps
1014151909Sps			ctlbuf += FREEBSD32_ALIGN(copylen);
1015151909Sps			len    -= FREEBSD32_ALIGN(copylen);
1016151909Sps
1017151909Sps			if (CMSG_SPACE(datalen) < clen) {
1018151909Sps				clen -= CMSG_SPACE(datalen);
1019151909Sps				cm = (struct cmsghdr *)
1020151909Sps					((caddr_t)cm + CMSG_SPACE(datalen));
1021151909Sps			} else {
1022151909Sps				clen = 0;
1023151909Sps				cm = NULL;
1024151909Sps			}
1025151909Sps		}
1026151909Sps		m = m->m_next;
1027151909Sps	}
1028151909Sps
1029151909Sps	msg->msg_controllen = (len <= 0) ? maxlen :  ctlbuf - (caddr_t)msg->msg_control;
1030151909Sps
1031151909Spsexit:
1032151909Sps	return (error);
1033151909Sps
1034151909Sps}
1035151909Sps
1036147813Sjhbint
1037151359Spsfreebsd32_recvmsg(td, uap)
1038151359Sps	struct thread *td;
1039151359Sps	struct freebsd32_recvmsg_args /* {
1040151359Sps		int	s;
1041151359Sps		struct	msghdr32 *msg;
1042151359Sps		int	flags;
1043151359Sps	} */ *uap;
1044151359Sps{
1045151359Sps	struct msghdr msg;
1046151359Sps	struct msghdr32 m32;
1047151359Sps	struct iovec *uiov, *iov;
1048151909Sps	struct mbuf *control = NULL;
1049151909Sps	struct mbuf **controlp;
1050151909Sps
1051151359Sps	int error;
1052151359Sps	error = copyin(uap->msg, &m32, sizeof(m32));
1053151359Sps	if (error)
1054151359Sps		return (error);
1055151359Sps	error = freebsd32_copyinmsghdr(uap->msg, &msg);
1056151359Sps	if (error)
1057151359Sps		return (error);
1058160246Sjhb	error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov,
1059160246Sjhb	    EMSGSIZE);
1060151359Sps	if (error)
1061151359Sps		return (error);
1062151359Sps	msg.msg_flags = uap->flags;
1063151359Sps	uiov = msg.msg_iov;
1064151359Sps	msg.msg_iov = iov;
1065151909Sps
1066151909Sps	controlp = (msg.msg_control != NULL) ?  &control : NULL;
1067160249Sjhb	error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, controlp);
1068151359Sps	if (error == 0) {
1069151359Sps		msg.msg_iov = uiov;
1070151909Sps
1071151909Sps		if (control != NULL)
1072151909Sps			error = freebsd32_copy_msg_out(&msg, control);
1073151909Sps
1074151909Sps		if (error == 0)
1075151909Sps			error = freebsd32_copyoutmsghdr(&msg, uap->msg);
1076151359Sps	}
1077151359Sps	free(iov, M_IOV);
1078151909Sps
1079151909Sps	if (control != NULL)
1080151909Sps		m_freem(control);
1081151909Sps
1082151359Sps	return (error);
1083151359Sps}
1084151359Sps
1085151909Sps
1086151909Spsstatic int
1087151909Spsfreebsd32_convert_msg_in(struct mbuf **controlp)
1088151909Sps{
1089151909Sps	struct mbuf *control = *controlp;
1090151909Sps	struct cmsghdr *cm = mtod(control, struct cmsghdr *);
1091151909Sps	void *data;
1092151909Sps	socklen_t clen = control->m_len, datalen;
1093151909Sps	int error;
1094151909Sps
1095151909Sps	error = 0;
1096151909Sps	*controlp = NULL;
1097151909Sps
1098151909Sps	while (cm != NULL) {
1099151909Sps		if (sizeof(struct cmsghdr) > clen || cm->cmsg_len > clen) {
1100151909Sps			error = EINVAL;
1101151909Sps			break;
1102151909Sps		}
1103151909Sps
1104151909Sps		data = FREEBSD32_CMSG_DATA(cm);
1105151909Sps		datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
1106151909Sps
1107151909Sps		*controlp = sbcreatecontrol(data, datalen, cm->cmsg_type,
1108151909Sps		    cm->cmsg_level);
1109151909Sps		controlp = &(*controlp)->m_next;
1110151909Sps
1111151909Sps		if (FREEBSD32_CMSG_SPACE(datalen) < clen) {
1112151909Sps			clen -= FREEBSD32_CMSG_SPACE(datalen);
1113151909Sps			cm = (struct cmsghdr *)
1114151909Sps				((caddr_t)cm + FREEBSD32_CMSG_SPACE(datalen));
1115151909Sps		} else {
1116151909Sps			clen = 0;
1117151909Sps			cm = NULL;
1118151909Sps		}
1119151909Sps	}
1120151909Sps
1121151909Sps	m_freem(control);
1122151909Sps	return (error);
1123151909Sps}
1124151909Sps
1125151909Sps
1126151359Spsint
1127151359Spsfreebsd32_sendmsg(struct thread *td,
1128151359Sps		  struct freebsd32_sendmsg_args *uap)
1129151359Sps{
1130151359Sps	struct msghdr msg;
1131151359Sps	struct msghdr32 m32;
1132151359Sps	struct iovec *iov;
1133151909Sps	struct mbuf *control = NULL;
1134151909Sps	struct sockaddr *to = NULL;
1135151359Sps	int error;
1136151359Sps
1137151359Sps	error = copyin(uap->msg, &m32, sizeof(m32));
1138151359Sps	if (error)
1139151359Sps		return (error);
1140151359Sps	error = freebsd32_copyinmsghdr(uap->msg, &msg);
1141151359Sps	if (error)
1142151359Sps		return (error);
1143160246Sjhb	error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov,
1144160246Sjhb	    EMSGSIZE);
1145151359Sps	if (error)
1146151359Sps		return (error);
1147151359Sps	msg.msg_iov = iov;
1148151909Sps	if (msg.msg_name != NULL) {
1149151909Sps		error = getsockaddr(&to, msg.msg_name, msg.msg_namelen);
1150151909Sps		if (error) {
1151151909Sps			to = NULL;
1152151909Sps			goto out;
1153151909Sps		}
1154151909Sps		msg.msg_name = to;
1155151909Sps	}
1156151909Sps
1157151909Sps	if (msg.msg_control) {
1158151909Sps		if (msg.msg_controllen < sizeof(struct cmsghdr)) {
1159151909Sps			error = EINVAL;
1160151909Sps			goto out;
1161151909Sps		}
1162151909Sps
1163151909Sps		error = sockargs(&control, msg.msg_control,
1164151909Sps		    msg.msg_controllen, MT_CONTROL);
1165151909Sps		if (error)
1166151909Sps			goto out;
1167151909Sps
1168151909Sps		error = freebsd32_convert_msg_in(&control);
1169151909Sps		if (error)
1170151909Sps			goto out;
1171151909Sps	}
1172151909Sps
1173151909Sps	error = kern_sendit(td, uap->s, &msg, uap->flags, control,
1174151909Sps	    UIO_USERSPACE);
1175151909Sps
1176151909Spsout:
1177151359Sps	free(iov, M_IOV);
1178151909Sps	if (to)
1179151909Sps		free(to, M_SONAME);
1180151359Sps	return (error);
1181151359Sps}
1182151359Sps
1183151359Spsint
1184151359Spsfreebsd32_recvfrom(struct thread *td,
1185151359Sps		   struct freebsd32_recvfrom_args *uap)
1186151359Sps{
1187151359Sps	struct msghdr msg;
1188151359Sps	struct iovec aiov;
1189151359Sps	int error;
1190151359Sps
1191151359Sps	if (uap->fromlenaddr) {
1192160246Sjhb		error = copyin(PTRIN(uap->fromlenaddr), &msg.msg_namelen,
1193160246Sjhb		    sizeof(msg.msg_namelen));
1194151359Sps		if (error)
1195151359Sps			return (error);
1196151359Sps	} else {
1197151359Sps		msg.msg_namelen = 0;
1198151359Sps	}
1199151359Sps
1200160246Sjhb	msg.msg_name = PTRIN(uap->from);
1201151359Sps	msg.msg_iov = &aiov;
1202151359Sps	msg.msg_iovlen = 1;
1203160246Sjhb	aiov.iov_base = PTRIN(uap->buf);
1204151359Sps	aiov.iov_len = uap->len;
1205160246Sjhb	msg.msg_control = NULL;
1206151359Sps	msg.msg_flags = uap->flags;
1207160249Sjhb	error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, NULL);
1208160249Sjhb	if (error == 0 && uap->fromlenaddr)
1209160249Sjhb		error = copyout(&msg.msg_namelen, PTRIN(uap->fromlenaddr),
1210160249Sjhb		    sizeof (msg.msg_namelen));
1211151359Sps	return (error);
1212151359Sps}
1213151359Sps
1214151359Spsint
1215119333Speterfreebsd32_settimeofday(struct thread *td,
1216119333Speter		       struct freebsd32_settimeofday_args *uap)
1217100384Speter{
1218144450Sjhb	struct timeval32 tv32;
1219144450Sjhb	struct timeval tv, *tvp;
1220144450Sjhb	struct timezone tz, *tzp;
1221100384Speter	int error;
1222100384Speter
1223144450Sjhb	if (uap->tv) {
1224144450Sjhb		error = copyin(uap->tv, &tv32, sizeof(tv32));
1225100384Speter		if (error)
1226100384Speter			return (error);
1227144450Sjhb		CP(tv32, tv, tv_sec);
1228144450Sjhb		CP(tv32, tv, tv_usec);
1229144450Sjhb		tvp = &tv;
1230144450Sjhb	} else
1231144450Sjhb		tvp = NULL;
1232144450Sjhb	if (uap->tzp) {
1233144450Sjhb		error = copyin(uap->tzp, &tz, sizeof(tz));
1234100384Speter		if (error)
1235100384Speter			return (error);
1236144450Sjhb		tzp = &tz;
1237144450Sjhb	} else
1238144450Sjhb		tzp = NULL;
1239144450Sjhb	return (kern_settimeofday(td, tvp, tzp));
1240100384Speter}
1241100384Speter
1242100384Speterint
1243119333Speterfreebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
1244100384Speter{
1245142059Sjhb	struct timeval32 s32[2];
1246142059Sjhb	struct timeval s[2], *sp;
1247100384Speter	int error;
1248100384Speter
1249142059Sjhb	if (uap->tptr != NULL) {
1250142059Sjhb		error = copyin(uap->tptr, s32, sizeof(s32));
1251100384Speter		if (error)
1252100384Speter			return (error);
1253100384Speter		CP(s32[0], s[0], tv_sec);
1254100384Speter		CP(s32[0], s[0], tv_usec);
1255100384Speter		CP(s32[1], s[1], tv_sec);
1256100384Speter		CP(s32[1], s[1], tv_usec);
1257142059Sjhb		sp = s;
1258142059Sjhb	} else
1259142059Sjhb		sp = NULL;
1260142059Sjhb	return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
1261100384Speter}
1262100384Speter
1263100384Speterint
1264154586Sambriskofreebsd32_lutimes(struct thread *td, struct freebsd32_lutimes_args *uap)
1265154586Sambrisko{
1266154586Sambrisko	struct timeval32 s32[2];
1267154586Sambrisko	struct timeval s[2], *sp;
1268154586Sambrisko	int error;
1269154586Sambrisko
1270154586Sambrisko	if (uap->tptr != NULL) {
1271154586Sambrisko		error = copyin(uap->tptr, s32, sizeof(s32));
1272154586Sambrisko		if (error)
1273154586Sambrisko			return (error);
1274154586Sambrisko		CP(s32[0], s[0], tv_sec);
1275154586Sambrisko		CP(s32[0], s[0], tv_usec);
1276154586Sambrisko		CP(s32[1], s[1], tv_sec);
1277154586Sambrisko		CP(s32[1], s[1], tv_usec);
1278154586Sambrisko		sp = s;
1279154586Sambrisko	} else
1280154586Sambrisko		sp = NULL;
1281154586Sambrisko	return (kern_lutimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
1282154586Sambrisko}
1283154586Sambrisko
1284154586Sambriskoint
1285153247Sambriskofreebsd32_futimes(struct thread *td, struct freebsd32_futimes_args *uap)
1286153247Sambrisko{
1287153247Sambrisko	struct timeval32 s32[2];
1288153247Sambrisko	struct timeval s[2], *sp;
1289153247Sambrisko	int error;
1290153247Sambrisko
1291153247Sambrisko	if (uap->tptr != NULL) {
1292153247Sambrisko		error = copyin(uap->tptr, s32, sizeof(s32));
1293153247Sambrisko		if (error)
1294153247Sambrisko			return (error);
1295153247Sambrisko		CP(s32[0], s[0], tv_sec);
1296153247Sambrisko		CP(s32[0], s[0], tv_usec);
1297153247Sambrisko		CP(s32[1], s[1], tv_sec);
1298153247Sambrisko		CP(s32[1], s[1], tv_usec);
1299153247Sambrisko		sp = s;
1300153247Sambrisko	} else
1301153247Sambrisko		sp = NULL;
1302153247Sambrisko	return (kern_futimes(td, uap->fd, sp, UIO_SYSSPACE));
1303153247Sambrisko}
1304153247Sambrisko
1305177789Skibint
1306177789Skibfreebsd32_futimesat(struct thread *td, struct freebsd32_futimesat_args *uap)
1307177789Skib{
1308177789Skib	struct timeval32 s32[2];
1309177789Skib	struct timeval s[2], *sp;
1310177789Skib	int error;
1311153247Sambrisko
1312177789Skib	if (uap->times != NULL) {
1313177789Skib		error = copyin(uap->times, s32, sizeof(s32));
1314177789Skib		if (error)
1315177789Skib			return (error);
1316177789Skib		CP(s32[0], s[0], tv_sec);
1317177789Skib		CP(s32[0], s[0], tv_usec);
1318177789Skib		CP(s32[1], s[1], tv_sec);
1319177789Skib		CP(s32[1], s[1], tv_usec);
1320177789Skib		sp = s;
1321177789Skib	} else
1322177789Skib		sp = NULL;
1323177789Skib	return (kern_utimesat(td, uap->fd, uap->path, UIO_USERSPACE,
1324177789Skib		sp, UIO_SYSSPACE));
1325177789Skib}
1326177789Skib
1327153247Sambriskoint
1328119333Speterfreebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
1329100384Speter{
1330144450Sjhb	struct timeval32 tv32;
1331144450Sjhb	struct timeval delta, olddelta, *deltap;
1332100384Speter	int error;
1333100384Speter
1334144450Sjhb	if (uap->delta) {
1335144450Sjhb		error = copyin(uap->delta, &tv32, sizeof(tv32));
1336100384Speter		if (error)
1337100384Speter			return (error);
1338144450Sjhb		CP(tv32, delta, tv_sec);
1339144450Sjhb		CP(tv32, delta, tv_usec);
1340144450Sjhb		deltap = &delta;
1341144450Sjhb	} else
1342144450Sjhb		deltap = NULL;
1343144450Sjhb	error = kern_adjtime(td, deltap, &olddelta);
1344144450Sjhb	if (uap->olddelta && error == 0) {
1345144450Sjhb		CP(olddelta, tv32, tv_sec);
1346144450Sjhb		CP(olddelta, tv32, tv_usec);
1347144450Sjhb		error = copyout(&tv32, uap->olddelta, sizeof(tv32));
1348100384Speter	}
1349100384Speter	return (error);
1350100384Speter}
1351100384Speter
1352128597Smarcel#ifdef COMPAT_FREEBSD4
1353100384Speterint
1354128260Speterfreebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)
1355100384Speter{
1356142059Sjhb	struct statfs32 s32;
1357142059Sjhb	struct statfs s;
1358100384Speter	int error;
1359100384Speter
1360142059Sjhb	error = kern_statfs(td, uap->path, UIO_USERSPACE, &s);
1361100384Speter	if (error)
1362100384Speter		return (error);
1363174526Sjhb	copy_statfs(&s, &s32);
1364142059Sjhb	return (copyout(&s32, uap->buf, sizeof(s32)));
1365100384Speter}
1366128597Smarcel#endif
1367100384Speter
1368128597Smarcel#ifdef COMPAT_FREEBSD4
1369100384Speterint
1370128260Speterfreebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)
1371100384Speter{
1372142059Sjhb	struct statfs32 s32;
1373142059Sjhb	struct statfs s;
1374100384Speter	int error;
1375100384Speter
1376142059Sjhb	error = kern_fstatfs(td, uap->fd, &s);
1377100384Speter	if (error)
1378100384Speter		return (error);
1379174526Sjhb	copy_statfs(&s, &s32);
1380142059Sjhb	return (copyout(&s32, uap->buf, sizeof(s32)));
1381100384Speter}
1382128597Smarcel#endif
1383100384Speter
1384128597Smarcel#ifdef COMPAT_FREEBSD4
1385100384Speterint
1386128260Speterfreebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)
1387128260Speter{
1388142059Sjhb	struct statfs32 s32;
1389142059Sjhb	struct statfs s;
1390142059Sjhb	fhandle_t fh;
1391128260Speter	int error;
1392128260Speter
1393142059Sjhb	if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
1394142059Sjhb		return (error);
1395142059Sjhb	error = kern_fhstatfs(td, fh, &s);
1396128260Speter	if (error)
1397128260Speter		return (error);
1398174526Sjhb	copy_statfs(&s, &s32);
1399142059Sjhb	return (copyout(&s32, uap->buf, sizeof(s32)));
1400128260Speter}
1401128597Smarcel#endif
1402128260Speter
1403194910Sjhb#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
1404194910Sjhb    defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
1405174381Sjhbstatic void
1406194910Sjhbfreebsd32_ipcperm_old_in(struct ipc_perm32_old *ip32, struct ipc_perm *ip)
1407194910Sjhb{
1408194910Sjhb
1409194910Sjhb	CP(*ip32, *ip, cuid);
1410194910Sjhb	CP(*ip32, *ip, cgid);
1411194910Sjhb	CP(*ip32, *ip, uid);
1412194910Sjhb	CP(*ip32, *ip, gid);
1413194910Sjhb	CP(*ip32, *ip, mode);
1414194910Sjhb	CP(*ip32, *ip, seq);
1415194910Sjhb	CP(*ip32, *ip, key);
1416194910Sjhb}
1417194910Sjhb
1418194910Sjhbstatic void
1419194910Sjhbfreebsd32_ipcperm_old_out(struct ipc_perm *ip, struct ipc_perm32_old *ip32)
1420194910Sjhb{
1421194910Sjhb
1422194910Sjhb	CP(*ip, *ip32, cuid);
1423194910Sjhb	CP(*ip, *ip32, cgid);
1424194910Sjhb	CP(*ip, *ip32, uid);
1425194910Sjhb	CP(*ip, *ip32, gid);
1426194910Sjhb	CP(*ip, *ip32, mode);
1427194910Sjhb	CP(*ip, *ip32, seq);
1428194910Sjhb	CP(*ip, *ip32, key);
1429194910Sjhb}
1430194910Sjhb#endif
1431194910Sjhb
1432194910Sjhbstatic void
1433174381Sjhbfreebsd32_ipcperm_in(struct ipc_perm32 *ip32, struct ipc_perm *ip)
1434174381Sjhb{
1435174381Sjhb
1436174381Sjhb	CP(*ip32, *ip, cuid);
1437174381Sjhb	CP(*ip32, *ip, cgid);
1438174381Sjhb	CP(*ip32, *ip, uid);
1439174381Sjhb	CP(*ip32, *ip, gid);
1440174381Sjhb	CP(*ip32, *ip, mode);
1441174381Sjhb	CP(*ip32, *ip, seq);
1442174381Sjhb	CP(*ip32, *ip, key);
1443174381Sjhb}
1444174381Sjhb
1445174381Sjhbstatic void
1446174381Sjhbfreebsd32_ipcperm_out(struct ipc_perm *ip, struct ipc_perm32 *ip32)
1447174381Sjhb{
1448174381Sjhb
1449174381Sjhb	CP(*ip, *ip32, cuid);
1450174381Sjhb	CP(*ip, *ip32, cgid);
1451174381Sjhb	CP(*ip, *ip32, uid);
1452174381Sjhb	CP(*ip, *ip32, gid);
1453174381Sjhb	CP(*ip, *ip32, mode);
1454174381Sjhb	CP(*ip, *ip32, seq);
1455174381Sjhb	CP(*ip, *ip32, key);
1456174381Sjhb}
1457174381Sjhb
1458128260Speterint
1459119333Speterfreebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
1460100384Speter{
1461174381Sjhb
1462194910Sjhb#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
1463194910Sjhb    defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
1464174381Sjhb	switch (uap->which) {
1465174381Sjhb	case 0:
1466195911Sjhb		return (freebsd7_freebsd32_semctl(td,
1467195911Sjhb		    (struct freebsd7_freebsd32_semctl_args *)&uap->a2));
1468174381Sjhb	default:
1469174381Sjhb		return (semsys(td, (struct semsys_args *)uap));
1470174381Sjhb	}
1471194910Sjhb#else
1472194910Sjhb	return (nosys(td, NULL));
1473194910Sjhb#endif
1474100384Speter}
1475100384Speter
1476194910Sjhb#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
1477194910Sjhb    defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
1478100384Speterint
1479194910Sjhbfreebsd7_freebsd32_semctl(struct thread *td,
1480194910Sjhb    struct freebsd7_freebsd32_semctl_args *uap)
1481194910Sjhb{
1482194910Sjhb	struct semid_ds32_old dsbuf32;
1483194910Sjhb	struct semid_ds dsbuf;
1484194910Sjhb	union semun semun;
1485194910Sjhb	union semun32 arg;
1486194910Sjhb	register_t rval;
1487194910Sjhb	int error;
1488194910Sjhb
1489194910Sjhb	switch (uap->cmd) {
1490194910Sjhb	case SEM_STAT:
1491194910Sjhb	case IPC_SET:
1492194910Sjhb	case IPC_STAT:
1493194910Sjhb	case GETALL:
1494194910Sjhb	case SETVAL:
1495194910Sjhb	case SETALL:
1496194910Sjhb		error = copyin(uap->arg, &arg, sizeof(arg));
1497194910Sjhb		if (error)
1498194910Sjhb			return (error);
1499194910Sjhb		break;
1500194910Sjhb	}
1501194910Sjhb
1502194910Sjhb	switch (uap->cmd) {
1503194910Sjhb	case SEM_STAT:
1504194910Sjhb	case IPC_STAT:
1505194910Sjhb		semun.buf = &dsbuf;
1506194910Sjhb		break;
1507194910Sjhb	case IPC_SET:
1508194910Sjhb		error = copyin(PTRIN(arg.buf), &dsbuf32, sizeof(dsbuf32));
1509194910Sjhb		if (error)
1510194910Sjhb			return (error);
1511194910Sjhb		freebsd32_ipcperm_old_in(&dsbuf32.sem_perm, &dsbuf.sem_perm);
1512194910Sjhb		PTRIN_CP(dsbuf32, dsbuf, sem_base);
1513194910Sjhb		CP(dsbuf32, dsbuf, sem_nsems);
1514194910Sjhb		CP(dsbuf32, dsbuf, sem_otime);
1515194910Sjhb		CP(dsbuf32, dsbuf, sem_ctime);
1516194910Sjhb		semun.buf = &dsbuf;
1517194910Sjhb		break;
1518194910Sjhb	case GETALL:
1519194910Sjhb	case SETALL:
1520194910Sjhb		semun.array = PTRIN(arg.array);
1521194910Sjhb		break;
1522194910Sjhb	case SETVAL:
1523194910Sjhb		semun.val = arg.val;
1524194910Sjhb		break;
1525194910Sjhb	}
1526194910Sjhb
1527194910Sjhb	error = kern_semctl(td, uap->semid, uap->semnum, uap->cmd, &semun,
1528194910Sjhb	    &rval);
1529194910Sjhb	if (error)
1530194910Sjhb		return (error);
1531194910Sjhb
1532194910Sjhb	switch (uap->cmd) {
1533194910Sjhb	case SEM_STAT:
1534194910Sjhb	case IPC_STAT:
1535194910Sjhb		bzero(&dsbuf32, sizeof(dsbuf32));
1536194910Sjhb		freebsd32_ipcperm_old_out(&dsbuf.sem_perm, &dsbuf32.sem_perm);
1537194910Sjhb		PTROUT_CP(dsbuf, dsbuf32, sem_base);
1538194910Sjhb		CP(dsbuf, dsbuf32, sem_nsems);
1539194910Sjhb		CP(dsbuf, dsbuf32, sem_otime);
1540194910Sjhb		CP(dsbuf, dsbuf32, sem_ctime);
1541194910Sjhb		error = copyout(&dsbuf32, PTRIN(arg.buf), sizeof(dsbuf32));
1542194910Sjhb		break;
1543194910Sjhb	}
1544194910Sjhb
1545194910Sjhb	if (error == 0)
1546194910Sjhb		td->td_retval[0] = rval;
1547194910Sjhb	return (error);
1548194910Sjhb}
1549194910Sjhb#endif
1550194910Sjhb
1551194910Sjhbint
1552174381Sjhbfreebsd32_semctl(struct thread *td, struct freebsd32_semctl_args *uap)
1553174381Sjhb{
1554174381Sjhb	struct semid_ds32 dsbuf32;
1555174381Sjhb	struct semid_ds dsbuf;
1556174381Sjhb	union semun semun;
1557174381Sjhb	union semun32 arg;
1558174381Sjhb	register_t rval;
1559174381Sjhb	int error;
1560174381Sjhb
1561174381Sjhb	switch (uap->cmd) {
1562174381Sjhb	case SEM_STAT:
1563174381Sjhb	case IPC_SET:
1564174381Sjhb	case IPC_STAT:
1565174381Sjhb	case GETALL:
1566174381Sjhb	case SETVAL:
1567174381Sjhb	case SETALL:
1568174381Sjhb		error = copyin(uap->arg, &arg, sizeof(arg));
1569174381Sjhb		if (error)
1570174381Sjhb			return (error);
1571174381Sjhb		break;
1572174381Sjhb	}
1573174381Sjhb
1574174381Sjhb	switch (uap->cmd) {
1575174381Sjhb	case SEM_STAT:
1576174381Sjhb	case IPC_STAT:
1577174381Sjhb		semun.buf = &dsbuf;
1578174381Sjhb		break;
1579174381Sjhb	case IPC_SET:
1580174381Sjhb		error = copyin(PTRIN(arg.buf), &dsbuf32, sizeof(dsbuf32));
1581174381Sjhb		if (error)
1582174381Sjhb			return (error);
1583174381Sjhb		freebsd32_ipcperm_in(&dsbuf32.sem_perm, &dsbuf.sem_perm);
1584174381Sjhb		PTRIN_CP(dsbuf32, dsbuf, sem_base);
1585174381Sjhb		CP(dsbuf32, dsbuf, sem_nsems);
1586174381Sjhb		CP(dsbuf32, dsbuf, sem_otime);
1587174381Sjhb		CP(dsbuf32, dsbuf, sem_ctime);
1588174381Sjhb		semun.buf = &dsbuf;
1589174381Sjhb		break;
1590174381Sjhb	case GETALL:
1591174381Sjhb	case SETALL:
1592174381Sjhb		semun.array = PTRIN(arg.array);
1593174381Sjhb		break;
1594174381Sjhb	case SETVAL:
1595174381Sjhb		semun.val = arg.val;
1596174381Sjhb		break;
1597174381Sjhb	}
1598174381Sjhb
1599174381Sjhb	error = kern_semctl(td, uap->semid, uap->semnum, uap->cmd, &semun,
1600174381Sjhb	    &rval);
1601174381Sjhb	if (error)
1602174381Sjhb		return (error);
1603174381Sjhb
1604174381Sjhb	switch (uap->cmd) {
1605174381Sjhb	case SEM_STAT:
1606174381Sjhb	case IPC_STAT:
1607194910Sjhb		bzero(&dsbuf32, sizeof(dsbuf32));
1608174381Sjhb		freebsd32_ipcperm_out(&dsbuf.sem_perm, &dsbuf32.sem_perm);
1609174381Sjhb		PTROUT_CP(dsbuf, dsbuf32, sem_base);
1610174381Sjhb		CP(dsbuf, dsbuf32, sem_nsems);
1611174381Sjhb		CP(dsbuf, dsbuf32, sem_otime);
1612174381Sjhb		CP(dsbuf, dsbuf32, sem_ctime);
1613174381Sjhb		error = copyout(&dsbuf32, PTRIN(arg.buf), sizeof(dsbuf32));
1614174381Sjhb		break;
1615174381Sjhb	}
1616174381Sjhb
1617174381Sjhb	if (error == 0)
1618174381Sjhb		td->td_retval[0] = rval;
1619174381Sjhb	return (error);
1620174381Sjhb}
1621174381Sjhb
1622174381Sjhbint
1623119333Speterfreebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
1624100384Speter{
1625174381Sjhb
1626194910Sjhb#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
1627194910Sjhb    defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
1628165405Sjkim	switch (uap->which) {
1629174381Sjhb	case 0:
1630195911Sjhb		return (freebsd7_freebsd32_msgctl(td,
1631195911Sjhb		    (struct freebsd7_freebsd32_msgctl_args *)&uap->a2));
1632165405Sjkim	case 2:
1633165405Sjkim		return (freebsd32_msgsnd(td,
1634165405Sjkim		    (struct freebsd32_msgsnd_args *)&uap->a2));
1635165405Sjkim	case 3:
1636165405Sjkim		return (freebsd32_msgrcv(td,
1637165405Sjkim		    (struct freebsd32_msgrcv_args *)&uap->a2));
1638165405Sjkim	default:
1639174381Sjhb		return (msgsys(td, (struct msgsys_args *)uap));
1640165405Sjkim	}
1641194910Sjhb#else
1642194910Sjhb	return (nosys(td, NULL));
1643194910Sjhb#endif
1644100384Speter}
1645100384Speter
1646194910Sjhb#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
1647194910Sjhb    defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
1648100384Speterint
1649194910Sjhbfreebsd7_freebsd32_msgctl(struct thread *td,
1650194910Sjhb    struct freebsd7_freebsd32_msgctl_args *uap)
1651194910Sjhb{
1652194910Sjhb	struct msqid_ds msqbuf;
1653194910Sjhb	struct msqid_ds32_old msqbuf32;
1654194910Sjhb	int error;
1655194910Sjhb
1656194910Sjhb	if (uap->cmd == IPC_SET) {
1657194910Sjhb		error = copyin(uap->buf, &msqbuf32, sizeof(msqbuf32));
1658194910Sjhb		if (error)
1659194910Sjhb			return (error);
1660194910Sjhb		freebsd32_ipcperm_old_in(&msqbuf32.msg_perm, &msqbuf.msg_perm);
1661194910Sjhb		PTRIN_CP(msqbuf32, msqbuf, msg_first);
1662194910Sjhb		PTRIN_CP(msqbuf32, msqbuf, msg_last);
1663194910Sjhb		CP(msqbuf32, msqbuf, msg_cbytes);
1664194910Sjhb		CP(msqbuf32, msqbuf, msg_qnum);
1665194910Sjhb		CP(msqbuf32, msqbuf, msg_qbytes);
1666194910Sjhb		CP(msqbuf32, msqbuf, msg_lspid);
1667194910Sjhb		CP(msqbuf32, msqbuf, msg_lrpid);
1668194910Sjhb		CP(msqbuf32, msqbuf, msg_stime);
1669194910Sjhb		CP(msqbuf32, msqbuf, msg_rtime);
1670194910Sjhb		CP(msqbuf32, msqbuf, msg_ctime);
1671194910Sjhb	}
1672194910Sjhb	error = kern_msgctl(td, uap->msqid, uap->cmd, &msqbuf);
1673194910Sjhb	if (error)
1674194910Sjhb		return (error);
1675194910Sjhb	if (uap->cmd == IPC_STAT) {
1676194910Sjhb		bzero(&msqbuf32, sizeof(msqbuf32));
1677194910Sjhb		freebsd32_ipcperm_old_out(&msqbuf.msg_perm, &msqbuf32.msg_perm);
1678194910Sjhb		PTROUT_CP(msqbuf, msqbuf32, msg_first);
1679194910Sjhb		PTROUT_CP(msqbuf, msqbuf32, msg_last);
1680194910Sjhb		CP(msqbuf, msqbuf32, msg_cbytes);
1681194910Sjhb		CP(msqbuf, msqbuf32, msg_qnum);
1682194910Sjhb		CP(msqbuf, msqbuf32, msg_qbytes);
1683194910Sjhb		CP(msqbuf, msqbuf32, msg_lspid);
1684194910Sjhb		CP(msqbuf, msqbuf32, msg_lrpid);
1685194910Sjhb		CP(msqbuf, msqbuf32, msg_stime);
1686194910Sjhb		CP(msqbuf, msqbuf32, msg_rtime);
1687194910Sjhb		CP(msqbuf, msqbuf32, msg_ctime);
1688194910Sjhb		error = copyout(&msqbuf32, uap->buf, sizeof(struct msqid_ds32));
1689194910Sjhb	}
1690194910Sjhb	return (error);
1691194910Sjhb}
1692194910Sjhb#endif
1693194910Sjhb
1694194910Sjhbint
1695174381Sjhbfreebsd32_msgctl(struct thread *td, struct freebsd32_msgctl_args *uap)
1696174381Sjhb{
1697174381Sjhb	struct msqid_ds msqbuf;
1698174381Sjhb	struct msqid_ds32 msqbuf32;
1699174381Sjhb	int error;
1700174381Sjhb
1701174381Sjhb	if (uap->cmd == IPC_SET) {
1702174381Sjhb		error = copyin(uap->buf, &msqbuf32, sizeof(msqbuf32));
1703174381Sjhb		if (error)
1704174381Sjhb			return (error);
1705174381Sjhb		freebsd32_ipcperm_in(&msqbuf32.msg_perm, &msqbuf.msg_perm);
1706174381Sjhb		PTRIN_CP(msqbuf32, msqbuf, msg_first);
1707174381Sjhb		PTRIN_CP(msqbuf32, msqbuf, msg_last);
1708174381Sjhb		CP(msqbuf32, msqbuf, msg_cbytes);
1709174381Sjhb		CP(msqbuf32, msqbuf, msg_qnum);
1710174381Sjhb		CP(msqbuf32, msqbuf, msg_qbytes);
1711174381Sjhb		CP(msqbuf32, msqbuf, msg_lspid);
1712174381Sjhb		CP(msqbuf32, msqbuf, msg_lrpid);
1713174381Sjhb		CP(msqbuf32, msqbuf, msg_stime);
1714174381Sjhb		CP(msqbuf32, msqbuf, msg_rtime);
1715174381Sjhb		CP(msqbuf32, msqbuf, msg_ctime);
1716174381Sjhb	}
1717174381Sjhb	error = kern_msgctl(td, uap->msqid, uap->cmd, &msqbuf);
1718174381Sjhb	if (error)
1719174381Sjhb		return (error);
1720174381Sjhb	if (uap->cmd == IPC_STAT) {
1721174381Sjhb		freebsd32_ipcperm_out(&msqbuf.msg_perm, &msqbuf32.msg_perm);
1722174381Sjhb		PTROUT_CP(msqbuf, msqbuf32, msg_first);
1723174381Sjhb		PTROUT_CP(msqbuf, msqbuf32, msg_last);
1724174381Sjhb		CP(msqbuf, msqbuf32, msg_cbytes);
1725174381Sjhb		CP(msqbuf, msqbuf32, msg_qnum);
1726174381Sjhb		CP(msqbuf, msqbuf32, msg_qbytes);
1727174381Sjhb		CP(msqbuf, msqbuf32, msg_lspid);
1728174381Sjhb		CP(msqbuf, msqbuf32, msg_lrpid);
1729174381Sjhb		CP(msqbuf, msqbuf32, msg_stime);
1730174381Sjhb		CP(msqbuf, msqbuf32, msg_rtime);
1731174381Sjhb		CP(msqbuf, msqbuf32, msg_ctime);
1732174381Sjhb		error = copyout(&msqbuf32, uap->buf, sizeof(struct msqid_ds32));
1733174381Sjhb	}
1734174381Sjhb	return (error);
1735174381Sjhb}
1736174381Sjhb
1737174381Sjhbint
1738165405Sjkimfreebsd32_msgsnd(struct thread *td, struct freebsd32_msgsnd_args *uap)
1739165405Sjkim{
1740165405Sjkim	const void *msgp;
1741165405Sjkim	long mtype;
1742165405Sjkim	int32_t mtype32;
1743165405Sjkim	int error;
1744165405Sjkim
1745165405Sjkim	msgp = PTRIN(uap->msgp);
1746165405Sjkim	if ((error = copyin(msgp, &mtype32, sizeof(mtype32))) != 0)
1747165405Sjkim		return (error);
1748165405Sjkim	mtype = mtype32;
1749165405Sjkim	return (kern_msgsnd(td, uap->msqid,
1750165405Sjkim	    (const char *)msgp + sizeof(mtype32),
1751165405Sjkim	    uap->msgsz, uap->msgflg, mtype));
1752165405Sjkim}
1753165405Sjkim
1754165405Sjkimint
1755165405Sjkimfreebsd32_msgrcv(struct thread *td, struct freebsd32_msgrcv_args *uap)
1756165405Sjkim{
1757165405Sjkim	void *msgp;
1758165405Sjkim	long mtype;
1759165405Sjkim	int32_t mtype32;
1760165405Sjkim	int error;
1761165405Sjkim
1762165405Sjkim	msgp = PTRIN(uap->msgp);
1763165405Sjkim	if ((error = kern_msgrcv(td, uap->msqid,
1764165405Sjkim	    (char *)msgp + sizeof(mtype32), uap->msgsz,
1765165405Sjkim	    uap->msgtyp, uap->msgflg, &mtype)) != 0)
1766165405Sjkim		return (error);
1767165405Sjkim	mtype32 = (int32_t)mtype;
1768165405Sjkim	return (copyout(&mtype32, msgp, sizeof(mtype32)));
1769165405Sjkim}
1770165405Sjkim
1771165405Sjkimint
1772119333Speterfreebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
1773100384Speter{
1774157285Sps
1775194910Sjhb#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
1776194910Sjhb    defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
1777157285Sps	switch (uap->which) {
1778157285Sps	case 0:	{	/* shmat */
1779157285Sps		struct shmat_args ap;
1780157285Sps
1781157285Sps		ap.shmid = uap->a2;
1782157285Sps		ap.shmaddr = PTRIN(uap->a3);
1783157285Sps		ap.shmflg = uap->a4;
1784157285Sps		return (sysent[SYS_shmat].sy_call(td, &ap));
1785157285Sps	}
1786157285Sps	case 2: {	/* shmdt */
1787157285Sps		struct shmdt_args ap;
1788157285Sps
1789157285Sps		ap.shmaddr = PTRIN(uap->a2);
1790157285Sps		return (sysent[SYS_shmdt].sy_call(td, &ap));
1791157285Sps	}
1792157285Sps	case 3: {	/* shmget */
1793157285Sps		struct shmget_args ap;
1794157285Sps
1795157285Sps		ap.key = uap->a2;
1796157285Sps		ap.size = uap->a3;
1797157285Sps		ap.shmflg = uap->a4;
1798157285Sps		return (sysent[SYS_shmget].sy_call(td, &ap));
1799157285Sps	}
1800157285Sps	case 4: {	/* shmctl */
1801195911Sjhb		struct freebsd7_freebsd32_shmctl_args ap;
1802157285Sps
1803157285Sps		ap.shmid = uap->a2;
1804157285Sps		ap.cmd = uap->a3;
1805157285Sps		ap.buf = PTRIN(uap->a4);
1806195911Sjhb		return (freebsd7_freebsd32_shmctl(td, &ap));
1807157285Sps	}
1808157285Sps	case 1:		/* oshmctl */
1809157285Sps	default:
1810157285Sps		return (EINVAL);
1811157285Sps	}
1812194910Sjhb#else
1813194910Sjhb	return (nosys(td, NULL));
1814194910Sjhb#endif
1815100384Speter}
1816100384Speter
1817194910Sjhb#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
1818194910Sjhb    defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
1819100384Speterint
1820194910Sjhbfreebsd7_freebsd32_shmctl(struct thread *td,
1821194910Sjhb    struct freebsd7_freebsd32_shmctl_args *uap)
1822194910Sjhb{
1823194910Sjhb	int error = 0;
1824194910Sjhb	union {
1825194910Sjhb		struct shmid_ds shmid_ds;
1826194910Sjhb		struct shm_info shm_info;
1827194910Sjhb		struct shminfo shminfo;
1828194910Sjhb	} u;
1829194910Sjhb	union {
1830194910Sjhb		struct shmid_ds32_old shmid_ds32;
1831194910Sjhb		struct shm_info32 shm_info32;
1832194910Sjhb		struct shminfo32 shminfo32;
1833194910Sjhb	} u32;
1834194910Sjhb	size_t sz;
1835194910Sjhb
1836194910Sjhb	if (uap->cmd == IPC_SET) {
1837194910Sjhb		if ((error = copyin(uap->buf, &u32.shmid_ds32,
1838194910Sjhb		    sizeof(u32.shmid_ds32))))
1839194910Sjhb			goto done;
1840194910Sjhb		freebsd32_ipcperm_old_in(&u32.shmid_ds32.shm_perm,
1841194910Sjhb		    &u.shmid_ds.shm_perm);
1842194910Sjhb		CP(u32.shmid_ds32, u.shmid_ds, shm_segsz);
1843194910Sjhb		CP(u32.shmid_ds32, u.shmid_ds, shm_lpid);
1844194910Sjhb		CP(u32.shmid_ds32, u.shmid_ds, shm_cpid);
1845194910Sjhb		CP(u32.shmid_ds32, u.shmid_ds, shm_nattch);
1846194910Sjhb		CP(u32.shmid_ds32, u.shmid_ds, shm_atime);
1847194910Sjhb		CP(u32.shmid_ds32, u.shmid_ds, shm_dtime);
1848194910Sjhb		CP(u32.shmid_ds32, u.shmid_ds, shm_ctime);
1849194910Sjhb	}
1850194910Sjhb
1851194910Sjhb	error = kern_shmctl(td, uap->shmid, uap->cmd, (void *)&u, &sz);
1852194910Sjhb	if (error)
1853194910Sjhb		goto done;
1854194910Sjhb
1855194910Sjhb	/* Cases in which we need to copyout */
1856194910Sjhb	switch (uap->cmd) {
1857194910Sjhb	case IPC_INFO:
1858194910Sjhb		CP(u.shminfo, u32.shminfo32, shmmax);
1859194910Sjhb		CP(u.shminfo, u32.shminfo32, shmmin);
1860194910Sjhb		CP(u.shminfo, u32.shminfo32, shmmni);
1861194910Sjhb		CP(u.shminfo, u32.shminfo32, shmseg);
1862194910Sjhb		CP(u.shminfo, u32.shminfo32, shmall);
1863194910Sjhb		error = copyout(&u32.shminfo32, uap->buf,
1864194910Sjhb		    sizeof(u32.shminfo32));
1865194910Sjhb		break;
1866194910Sjhb	case SHM_INFO:
1867194910Sjhb		CP(u.shm_info, u32.shm_info32, used_ids);
1868194910Sjhb		CP(u.shm_info, u32.shm_info32, shm_rss);
1869194910Sjhb		CP(u.shm_info, u32.shm_info32, shm_tot);
1870194910Sjhb		CP(u.shm_info, u32.shm_info32, shm_swp);
1871194910Sjhb		CP(u.shm_info, u32.shm_info32, swap_attempts);
1872194910Sjhb		CP(u.shm_info, u32.shm_info32, swap_successes);
1873194910Sjhb		error = copyout(&u32.shm_info32, uap->buf,
1874194910Sjhb		    sizeof(u32.shm_info32));
1875194910Sjhb		break;
1876194910Sjhb	case SHM_STAT:
1877194910Sjhb	case IPC_STAT:
1878194910Sjhb		freebsd32_ipcperm_old_out(&u.shmid_ds.shm_perm,
1879194910Sjhb		    &u32.shmid_ds32.shm_perm);
1880194910Sjhb		if (u.shmid_ds.shm_segsz > INT32_MAX)
1881194910Sjhb			u32.shmid_ds32.shm_segsz = INT32_MAX;
1882194910Sjhb		else
1883194910Sjhb			CP(u.shmid_ds, u32.shmid_ds32, shm_segsz);
1884194910Sjhb		CP(u.shmid_ds, u32.shmid_ds32, shm_lpid);
1885194910Sjhb		CP(u.shmid_ds, u32.shmid_ds32, shm_cpid);
1886194910Sjhb		CP(u.shmid_ds, u32.shmid_ds32, shm_nattch);
1887194910Sjhb		CP(u.shmid_ds, u32.shmid_ds32, shm_atime);
1888194910Sjhb		CP(u.shmid_ds, u32.shmid_ds32, shm_dtime);
1889194910Sjhb		CP(u.shmid_ds, u32.shmid_ds32, shm_ctime);
1890194910Sjhb		u32.shmid_ds32.shm_internal = 0;
1891194910Sjhb		error = copyout(&u32.shmid_ds32, uap->buf,
1892194910Sjhb		    sizeof(u32.shmid_ds32));
1893194910Sjhb		break;
1894194910Sjhb	}
1895194910Sjhb
1896194910Sjhbdone:
1897194910Sjhb	if (error) {
1898194910Sjhb		/* Invalidate the return value */
1899194910Sjhb		td->td_retval[0] = -1;
1900194910Sjhb	}
1901194910Sjhb	return (error);
1902194910Sjhb}
1903194910Sjhb#endif
1904194910Sjhb
1905194910Sjhbint
1906157285Spsfreebsd32_shmctl(struct thread *td, struct freebsd32_shmctl_args *uap)
1907157285Sps{
1908157285Sps	int error = 0;
1909157285Sps	union {
1910157285Sps		struct shmid_ds shmid_ds;
1911157285Sps		struct shm_info shm_info;
1912157285Sps		struct shminfo shminfo;
1913157285Sps	} u;
1914157285Sps	union {
1915157285Sps		struct shmid_ds32 shmid_ds32;
1916157285Sps		struct shm_info32 shm_info32;
1917157285Sps		struct shminfo32 shminfo32;
1918157285Sps	} u32;
1919157285Sps	size_t sz;
1920157285Sps
1921157285Sps	if (uap->cmd == IPC_SET) {
1922157285Sps		if ((error = copyin(uap->buf, &u32.shmid_ds32,
1923157285Sps		    sizeof(u32.shmid_ds32))))
1924157285Sps			goto done;
1925174381Sjhb		freebsd32_ipcperm_in(&u32.shmid_ds32.shm_perm,
1926174381Sjhb		    &u.shmid_ds.shm_perm);
1927157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_segsz);
1928157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_lpid);
1929157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_cpid);
1930157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_nattch);
1931157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_atime);
1932157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_dtime);
1933157285Sps		CP(u32.shmid_ds32, u.shmid_ds, shm_ctime);
1934157285Sps	}
1935157285Sps
1936157285Sps	error = kern_shmctl(td, uap->shmid, uap->cmd, (void *)&u, &sz);
1937157285Sps	if (error)
1938157285Sps		goto done;
1939157285Sps
1940157285Sps	/* Cases in which we need to copyout */
1941157285Sps	switch (uap->cmd) {
1942157285Sps	case IPC_INFO:
1943157285Sps		CP(u.shminfo, u32.shminfo32, shmmax);
1944157285Sps		CP(u.shminfo, u32.shminfo32, shmmin);
1945157285Sps		CP(u.shminfo, u32.shminfo32, shmmni);
1946157285Sps		CP(u.shminfo, u32.shminfo32, shmseg);
1947157285Sps		CP(u.shminfo, u32.shminfo32, shmall);
1948157285Sps		error = copyout(&u32.shminfo32, uap->buf,
1949157285Sps		    sizeof(u32.shminfo32));
1950157285Sps		break;
1951157285Sps	case SHM_INFO:
1952157285Sps		CP(u.shm_info, u32.shm_info32, used_ids);
1953157285Sps		CP(u.shm_info, u32.shm_info32, shm_rss);
1954157285Sps		CP(u.shm_info, u32.shm_info32, shm_tot);
1955157285Sps		CP(u.shm_info, u32.shm_info32, shm_swp);
1956157285Sps		CP(u.shm_info, u32.shm_info32, swap_attempts);
1957157285Sps		CP(u.shm_info, u32.shm_info32, swap_successes);
1958157285Sps		error = copyout(&u32.shm_info32, uap->buf,
1959157285Sps		    sizeof(u32.shm_info32));
1960157285Sps		break;
1961157285Sps	case SHM_STAT:
1962157285Sps	case IPC_STAT:
1963174381Sjhb		freebsd32_ipcperm_out(&u.shmid_ds.shm_perm,
1964174381Sjhb		    &u32.shmid_ds32.shm_perm);
1965194910Sjhb		if (u.shmid_ds.shm_segsz > INT32_MAX)
1966194910Sjhb			u32.shmid_ds32.shm_segsz = INT32_MAX;
1967194910Sjhb		else
1968194910Sjhb			CP(u.shmid_ds, u32.shmid_ds32, shm_segsz);
1969157285Sps		CP(u.shmid_ds, u32.shmid_ds32, shm_lpid);
1970157285Sps		CP(u.shmid_ds, u32.shmid_ds32, shm_cpid);
1971157285Sps		CP(u.shmid_ds, u32.shmid_ds32, shm_nattch);
1972157285Sps		CP(u.shmid_ds, u32.shmid_ds32, shm_atime);
1973157285Sps		CP(u.shmid_ds, u32.shmid_ds32, shm_dtime);
1974157285Sps		CP(u.shmid_ds, u32.shmid_ds32, shm_ctime);
1975157285Sps		error = copyout(&u32.shmid_ds32, uap->buf,
1976157285Sps		    sizeof(u32.shmid_ds32));
1977157285Sps		break;
1978157285Sps	}
1979157285Sps
1980157285Spsdone:
1981157285Sps	if (error) {
1982157285Sps		/* Invalidate the return value */
1983157285Sps		td->td_retval[0] = -1;
1984157285Sps	}
1985157285Sps	return (error);
1986157285Sps}
1987157285Sps
1988157285Spsint
1989119333Speterfreebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
1990100384Speter{
1991100384Speter	struct pread_args ap;
1992100384Speter
1993107849Salfred	ap.fd = uap->fd;
1994107849Salfred	ap.buf = uap->buf;
1995107849Salfred	ap.nbyte = uap->nbyte;
1996205014Snwhitehorn	ap.offset = PAIR32TO64(off_t,uap->offset);
1997100384Speter	return (pread(td, &ap));
1998100384Speter}
1999100384Speter
2000100384Speterint
2001119333Speterfreebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
2002100384Speter{
2003100384Speter	struct pwrite_args ap;
2004100384Speter
2005107849Salfred	ap.fd = uap->fd;
2006107849Salfred	ap.buf = uap->buf;
2007107849Salfred	ap.nbyte = uap->nbyte;
2008205014Snwhitehorn	ap.offset = PAIR32TO64(off_t,uap->offset);
2009100384Speter	return (pwrite(td, &ap));
2010100384Speter}
2011100384Speter
2012100384Speterint
2013119333Speterfreebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
2014100384Speter{
2015100384Speter	int error;
2016100384Speter	struct lseek_args ap;
2017100384Speter	off_t pos;
2018100384Speter
2019107849Salfred	ap.fd = uap->fd;
2020205014Snwhitehorn	ap.offset = PAIR32TO64(off_t,uap->offset);
2021107849Salfred	ap.whence = uap->whence;
2022100384Speter	error = lseek(td, &ap);
2023100384Speter	/* Expand the quad return into two parts for eax and edx */
2024100384Speter	pos = *(off_t *)(td->td_retval);
2025205014Snwhitehorn	td->td_retval[RETVAL_LO] = pos & 0xffffffff;	/* %eax */
2026205014Snwhitehorn	td->td_retval[RETVAL_HI] = pos >> 32;		/* %edx */
2027100384Speter	return error;
2028100384Speter}
2029100384Speter
2030100384Speterint
2031119333Speterfreebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
2032100384Speter{
2033100384Speter	struct truncate_args ap;
2034100384Speter
2035107849Salfred	ap.path = uap->path;
2036205014Snwhitehorn	ap.length = PAIR32TO64(off_t,uap->length);
2037100384Speter	return (truncate(td, &ap));
2038100384Speter}
2039100384Speter
2040100384Speterint
2041119333Speterfreebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
2042100384Speter{
2043100384Speter	struct ftruncate_args ap;
2044100384Speter
2045107849Salfred	ap.fd = uap->fd;
2046205014Snwhitehorn	ap.length = PAIR32TO64(off_t,uap->length);
2047100384Speter	return (ftruncate(td, &ap));
2048100384Speter}
2049100384Speter
2050184183Sjhbint
2051184183Sjhbfreebsd32_getdirentries(struct thread *td,
2052184183Sjhb    struct freebsd32_getdirentries_args *uap)
2053184183Sjhb{
2054184183Sjhb	long base;
2055184183Sjhb	int32_t base32;
2056184183Sjhb	int error;
2057184183Sjhb
2058184183Sjhb	error = kern_getdirentries(td, uap->fd, uap->buf, uap->count, &base);
2059184183Sjhb	if (error)
2060184183Sjhb		return (error);
2061184183Sjhb	if (uap->basep != NULL) {
2062184183Sjhb		base32 = base;
2063184183Sjhb		error = copyout(&base32, uap->basep, sizeof(int32_t));
2064184183Sjhb	}
2065184183Sjhb	return (error);
2066184183Sjhb}
2067184183Sjhb
2068171215Speter#ifdef COMPAT_FREEBSD6
2069171215Speter/* versions with the 'int pad' argument */
2070171215Speterint
2071171215Speterfreebsd6_freebsd32_pread(struct thread *td, struct freebsd6_freebsd32_pread_args *uap)
2072171215Speter{
2073171215Speter	struct pread_args ap;
2074171215Speter
2075171215Speter	ap.fd = uap->fd;
2076171215Speter	ap.buf = uap->buf;
2077171215Speter	ap.nbyte = uap->nbyte;
2078205014Snwhitehorn	ap.offset = PAIR32TO64(off_t,uap->offset);
2079171215Speter	return (pread(td, &ap));
2080171215Speter}
2081171215Speter
2082171215Speterint
2083171215Speterfreebsd6_freebsd32_pwrite(struct thread *td, struct freebsd6_freebsd32_pwrite_args *uap)
2084171215Speter{
2085171215Speter	struct pwrite_args ap;
2086171215Speter
2087171215Speter	ap.fd = uap->fd;
2088171215Speter	ap.buf = uap->buf;
2089171215Speter	ap.nbyte = uap->nbyte;
2090205014Snwhitehorn	ap.offset = PAIR32TO64(off_t,uap->offset);
2091171215Speter	return (pwrite(td, &ap));
2092171215Speter}
2093171215Speter
2094171215Speterint
2095171215Speterfreebsd6_freebsd32_lseek(struct thread *td, struct freebsd6_freebsd32_lseek_args *uap)
2096171215Speter{
2097171215Speter	int error;
2098171215Speter	struct lseek_args ap;
2099171215Speter	off_t pos;
2100171215Speter
2101171215Speter	ap.fd = uap->fd;
2102205014Snwhitehorn	ap.offset = PAIR32TO64(off_t,uap->offset);
2103171215Speter	ap.whence = uap->whence;
2104171215Speter	error = lseek(td, &ap);
2105171215Speter	/* Expand the quad return into two parts for eax and edx */
2106171215Speter	pos = *(off_t *)(td->td_retval);
2107205014Snwhitehorn	td->td_retval[RETVAL_LO] = pos & 0xffffffff;	/* %eax */
2108205014Snwhitehorn	td->td_retval[RETVAL_HI] = pos >> 32;		/* %edx */
2109171215Speter	return error;
2110171215Speter}
2111171215Speter
2112171215Speterint
2113171215Speterfreebsd6_freebsd32_truncate(struct thread *td, struct freebsd6_freebsd32_truncate_args *uap)
2114171215Speter{
2115171215Speter	struct truncate_args ap;
2116171215Speter
2117171215Speter	ap.path = uap->path;
2118205014Snwhitehorn	ap.length = PAIR32TO64(off_t,uap->length);
2119171215Speter	return (truncate(td, &ap));
2120171215Speter}
2121171215Speter
2122171215Speterint
2123171215Speterfreebsd6_freebsd32_ftruncate(struct thread *td, struct freebsd6_freebsd32_ftruncate_args *uap)
2124171215Speter{
2125171215Speter	struct ftruncate_args ap;
2126171215Speter
2127171215Speter	ap.fd = uap->fd;
2128205014Snwhitehorn	ap.length = PAIR32TO64(off_t,uap->length);
2129171215Speter	return (ftruncate(td, &ap));
2130171215Speter}
2131171215Speter#endif /* COMPAT_FREEBSD6 */
2132171215Speter
2133156114Spsstruct sf_hdtr32 {
2134156114Sps	uint32_t headers;
2135156114Sps	int hdr_cnt;
2136156114Sps	uint32_t trailers;
2137156114Sps	int trl_cnt;
2138156114Sps};
2139156114Sps
2140156114Spsstatic int
2141156114Spsfreebsd32_do_sendfile(struct thread *td,
2142156114Sps    struct freebsd32_sendfile_args *uap, int compat)
2143104738Speter{
2144156114Sps	struct sendfile_args ap;
2145156114Sps	struct sf_hdtr32 hdtr32;
2146156114Sps	struct sf_hdtr hdtr;
2147156114Sps	struct uio *hdr_uio, *trl_uio;
2148156114Sps	struct iovec32 *iov32;
2149156114Sps	int error;
2150104738Speter
2151156114Sps	hdr_uio = trl_uio = NULL;
2152156114Sps
2153107849Salfred	ap.fd = uap->fd;
2154107849Salfred	ap.s = uap->s;
2155205014Snwhitehorn	ap.offset = PAIR32TO64(off_t,uap->offset);
2156156114Sps	ap.nbytes = uap->nbytes;
2157156114Sps	ap.hdtr = (struct sf_hdtr *)uap->hdtr;		/* XXX not used */
2158156114Sps	ap.sbytes = uap->sbytes;
2159107849Salfred	ap.flags = uap->flags;
2160156114Sps
2161156114Sps	if (uap->hdtr != NULL) {
2162156114Sps		error = copyin(uap->hdtr, &hdtr32, sizeof(hdtr32));
2163156114Sps		if (error)
2164156114Sps			goto out;
2165156114Sps		PTRIN_CP(hdtr32, hdtr, headers);
2166156114Sps		CP(hdtr32, hdtr, hdr_cnt);
2167156114Sps		PTRIN_CP(hdtr32, hdtr, trailers);
2168156114Sps		CP(hdtr32, hdtr, trl_cnt);
2169156114Sps
2170156114Sps		if (hdtr.headers != NULL) {
2171160246Sjhb			iov32 = PTRIN(hdtr32.headers);
2172156114Sps			error = freebsd32_copyinuio(iov32,
2173156114Sps			    hdtr32.hdr_cnt, &hdr_uio);
2174156114Sps			if (error)
2175156114Sps				goto out;
2176156114Sps		}
2177156114Sps		if (hdtr.trailers != NULL) {
2178160246Sjhb			iov32 = PTRIN(hdtr32.trailers);
2179156114Sps			error = freebsd32_copyinuio(iov32,
2180156114Sps			    hdtr32.trl_cnt, &trl_uio);
2181156114Sps			if (error)
2182156114Sps				goto out;
2183156114Sps		}
2184156114Sps	}
2185156114Sps
2186156114Sps	error = kern_sendfile(td, &ap, hdr_uio, trl_uio, compat);
2187156114Spsout:
2188156114Sps	if (hdr_uio)
2189156114Sps		free(hdr_uio, M_IOV);
2190156114Sps	if (trl_uio)
2191156114Sps		free(trl_uio, M_IOV);
2192156114Sps	return (error);
2193104738Speter}
2194156114Sps
2195156114Sps#ifdef COMPAT_FREEBSD4
2196156114Spsint
2197156114Spsfreebsd4_freebsd32_sendfile(struct thread *td,
2198156114Sps    struct freebsd4_freebsd32_sendfile_args *uap)
2199156114Sps{
2200156114Sps	return (freebsd32_do_sendfile(td,
2201156114Sps	    (struct freebsd32_sendfile_args *)uap, 1));
2202156114Sps}
2203104738Speter#endif
2204104738Speter
2205104738Speterint
2206119333Speterfreebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
2207100384Speter{
2208100384Speter
2209156114Sps	return (freebsd32_do_sendfile(td, uap, 0));
2210100384Speter}
2211100384Speter
2212100384Speterstatic void
2213100384Spetercopy_stat( struct stat *in, struct stat32 *out)
2214100384Speter{
2215100384Speter	CP(*in, *out, st_dev);
2216100384Speter	CP(*in, *out, st_ino);
2217100384Speter	CP(*in, *out, st_mode);
2218100384Speter	CP(*in, *out, st_nlink);
2219100384Speter	CP(*in, *out, st_uid);
2220100384Speter	CP(*in, *out, st_gid);
2221100384Speter	CP(*in, *out, st_rdev);
2222100384Speter	TS_CP(*in, *out, st_atimespec);
2223100384Speter	TS_CP(*in, *out, st_mtimespec);
2224100384Speter	TS_CP(*in, *out, st_ctimespec);
2225100384Speter	CP(*in, *out, st_size);
2226100384Speter	CP(*in, *out, st_blocks);
2227100384Speter	CP(*in, *out, st_blksize);
2228100384Speter	CP(*in, *out, st_flags);
2229100384Speter	CP(*in, *out, st_gen);
2230100384Speter}
2231100384Speter
2232100384Speterint
2233119333Speterfreebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
2234100384Speter{
2235123746Speter	struct stat sb;
2236123746Speter	struct stat32 sb32;
2237100384Speter	int error;
2238100384Speter
2239142059Sjhb	error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
2240100384Speter	if (error)
2241100384Speter		return (error);
2242123746Speter	copy_stat(&sb, &sb32);
2243123746Speter	error = copyout(&sb32, uap->ub, sizeof (sb32));
2244100384Speter	return (error);
2245100384Speter}
2246100384Speter
2247100384Speterint
2248119333Speterfreebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
2249100384Speter{
2250123746Speter	struct stat ub;
2251123746Speter	struct stat32 ub32;
2252100384Speter	int error;
2253100384Speter
2254142059Sjhb	error = kern_fstat(td, uap->fd, &ub);
2255100384Speter	if (error)
2256100384Speter		return (error);
2257123746Speter	copy_stat(&ub, &ub32);
2258123746Speter	error = copyout(&ub32, uap->ub, sizeof(ub32));
2259100384Speter	return (error);
2260100384Speter}
2261100384Speter
2262100384Speterint
2263177789Skibfreebsd32_fstatat(struct thread *td, struct freebsd32_fstatat_args *uap)
2264177789Skib{
2265177789Skib	struct stat ub;
2266177789Skib	struct stat32 ub32;
2267177789Skib	int error;
2268177789Skib
2269177789Skib	error = kern_statat(td, uap->flag, uap->fd, uap->path, UIO_USERSPACE, &ub);
2270177789Skib	if (error)
2271177789Skib		return (error);
2272177789Skib	copy_stat(&ub, &ub32);
2273177789Skib	error = copyout(&ub32, uap->buf, sizeof(ub32));
2274177789Skib	return (error);
2275177789Skib}
2276177789Skib
2277177789Skibint
2278119333Speterfreebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
2279100384Speter{
2280123746Speter	struct stat sb;
2281123746Speter	struct stat32 sb32;
2282142059Sjhb	int error;
2283100384Speter
2284142059Sjhb	error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
2285100384Speter	if (error)
2286100384Speter		return (error);
2287123746Speter	copy_stat(&sb, &sb32);
2288123746Speter	error = copyout(&sb32, uap->ub, sizeof (sb32));
2289100384Speter	return (error);
2290100384Speter}
2291100384Speter
2292100384Speter/*
2293100384Speter * MPSAFE
2294100384Speter */
2295100384Speterint
2296119333Speterfreebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
2297100384Speter{
2298100384Speter	int error, name[CTL_MAXNAME];
2299100384Speter	size_t j, oldlen;
2300100384Speter
2301100384Speter	if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
2302100384Speter		return (EINVAL);
2303136404Speter 	error = copyin(uap->name, name, uap->namelen * sizeof(int));
2304100384Speter 	if (error)
2305100384Speter		return (error);
2306100384Speter	if (uap->oldlenp)
2307100384Speter		oldlen = fuword32(uap->oldlenp);
2308100384Speter	else
2309100384Speter		oldlen = 0;
2310100384Speter	error = userland_sysctl(td, name, uap->namelen,
2311100384Speter		uap->old, &oldlen, 1,
2312136404Speter		uap->new, uap->newlen, &j, SCTL_MASK32);
2313100384Speter	if (error && error != ENOMEM)
2314186564Sed		return (error);
2315136404Speter	if (uap->oldlenp)
2316100384Speter		suword32(uap->oldlenp, j);
2317186564Sed	return (0);
2318100384Speter}
2319100384Speter
2320100384Speterint
2321185435Sbzfreebsd32_jail(struct thread *td, struct freebsd32_jail_args *uap)
2322185435Sbz{
2323185435Sbz	uint32_t version;
2324185435Sbz	int error;
2325192895Sjamie	struct jail j;
2326185435Sbz
2327185435Sbz	error = copyin(uap->jail, &version, sizeof(uint32_t));
2328185435Sbz	if (error)
2329185435Sbz		return (error);
2330190466Sjamie
2331185435Sbz	switch (version) {
2332190466Sjamie	case 0:
2333185435Sbz	{
2334185435Sbz		/* FreeBSD single IPv4 jails. */
2335185435Sbz		struct jail32_v0 j32_v0;
2336185435Sbz
2337192895Sjamie		bzero(&j, sizeof(struct jail));
2338185435Sbz		error = copyin(uap->jail, &j32_v0, sizeof(struct jail32_v0));
2339185435Sbz		if (error)
2340185435Sbz			return (error);
2341192895Sjamie		CP(j32_v0, j, version);
2342192895Sjamie		PTRIN_CP(j32_v0, j, path);
2343192895Sjamie		PTRIN_CP(j32_v0, j, hostname);
2344192895Sjamie		j.ip4s = j32_v0.ip_number;
2345185435Sbz		break;
2346185435Sbz	}
2347185435Sbz
2348185435Sbz	case 1:
2349185435Sbz		/*
2350185435Sbz		 * Version 1 was used by multi-IPv4 jail implementations
2351185435Sbz		 * that never made it into the official kernel.
2352185435Sbz		 */
2353185435Sbz		return (EINVAL);
2354185435Sbz
2355185435Sbz	case 2:	/* JAIL_API_VERSION */
2356185435Sbz	{
2357185435Sbz		/* FreeBSD multi-IPv4/IPv6,noIP jails. */
2358185435Sbz		struct jail32 j32;
2359185435Sbz
2360185435Sbz		error = copyin(uap->jail, &j32, sizeof(struct jail32));
2361185435Sbz		if (error)
2362185435Sbz			return (error);
2363192895Sjamie		CP(j32, j, version);
2364192895Sjamie		PTRIN_CP(j32, j, path);
2365192895Sjamie		PTRIN_CP(j32, j, hostname);
2366192895Sjamie		PTRIN_CP(j32, j, jailname);
2367192895Sjamie		CP(j32, j, ip4s);
2368192895Sjamie		CP(j32, j, ip6s);
2369192895Sjamie		PTRIN_CP(j32, j, ip4);
2370192895Sjamie		PTRIN_CP(j32, j, ip6);
2371185435Sbz		break;
2372185435Sbz	}
2373185435Sbz
2374185435Sbz	default:
2375185435Sbz		/* Sci-Fi jails are not supported, sorry. */
2376185435Sbz		return (EINVAL);
2377185435Sbz	}
2378192895Sjamie	return (kern_jail(td, &j));
2379185435Sbz}
2380185435Sbz
2381185435Sbzint
2382191673Sjamiefreebsd32_jail_set(struct thread *td, struct freebsd32_jail_set_args *uap)
2383191673Sjamie{
2384191673Sjamie	struct uio *auio;
2385191673Sjamie	int error;
2386191673Sjamie
2387191673Sjamie	/* Check that we have an even number of iovecs. */
2388191673Sjamie	if (uap->iovcnt & 1)
2389191673Sjamie		return (EINVAL);
2390191673Sjamie
2391191673Sjamie	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
2392191673Sjamie	if (error)
2393191673Sjamie		return (error);
2394191673Sjamie	error = kern_jail_set(td, auio, uap->flags);
2395191673Sjamie	free(auio, M_IOV);
2396191673Sjamie	return (error);
2397191673Sjamie}
2398191673Sjamie
2399191673Sjamieint
2400191673Sjamiefreebsd32_jail_get(struct thread *td, struct freebsd32_jail_get_args *uap)
2401191673Sjamie{
2402191673Sjamie	struct iovec32 iov32;
2403191673Sjamie	struct uio *auio;
2404191673Sjamie	int error, i;
2405191673Sjamie
2406191673Sjamie	/* Check that we have an even number of iovecs. */
2407191673Sjamie	if (uap->iovcnt & 1)
2408191673Sjamie		return (EINVAL);
2409191673Sjamie
2410191673Sjamie	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
2411191673Sjamie	if (error)
2412191673Sjamie		return (error);
2413191673Sjamie	error = kern_jail_get(td, auio, uap->flags);
2414191673Sjamie	if (error == 0)
2415191673Sjamie		for (i = 0; i < uap->iovcnt; i++) {
2416191673Sjamie			PTROUT_CP(auio->uio_iov[i], iov32, iov_base);
2417191673Sjamie			CP(auio->uio_iov[i], iov32, iov_len);
2418191673Sjamie			error = copyout(&iov32, uap->iovp + i, sizeof(iov32));
2419191673Sjamie			if (error != 0)
2420191673Sjamie				break;
2421191673Sjamie		}
2422191673Sjamie	free(auio, M_IOV);
2423191673Sjamie	return (error);
2424191673Sjamie}
2425191673Sjamie
2426191673Sjamieint
2427119333Speterfreebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
2428100384Speter{
2429113859Sjhb	struct sigaction32 s32;
2430113859Sjhb	struct sigaction sa, osa, *sap;
2431100384Speter	int error;
2432100384Speter
2433113859Sjhb	if (uap->act) {
2434113859Sjhb		error = copyin(uap->act, &s32, sizeof(s32));
2435100384Speter		if (error)
2436100384Speter			return (error);
2437113859Sjhb		sa.sa_handler = PTRIN(s32.sa_u);
2438113859Sjhb		CP(s32, sa, sa_flags);
2439113859Sjhb		CP(s32, sa, sa_mask);
2440113859Sjhb		sap = &sa;
2441113859Sjhb	} else
2442113859Sjhb		sap = NULL;
2443113859Sjhb	error = kern_sigaction(td, uap->sig, sap, &osa, 0);
2444146583Sps	if (error == 0 && uap->oact != NULL) {
2445113859Sjhb		s32.sa_u = PTROUT(osa.sa_handler);
2446113859Sjhb		CP(osa, s32, sa_flags);
2447113859Sjhb		CP(osa, s32, sa_mask);
2448113859Sjhb		error = copyout(&s32, uap->oact, sizeof(s32));
2449100384Speter	}
2450100384Speter	return (error);
2451100384Speter}
2452100384Speter
2453114987Speter#ifdef COMPAT_FREEBSD4
2454114987Speterint
2455119333Speterfreebsd4_freebsd32_sigaction(struct thread *td,
2456119333Speter			     struct freebsd4_freebsd32_sigaction_args *uap)
2457114987Speter{
2458114987Speter	struct sigaction32 s32;
2459114987Speter	struct sigaction sa, osa, *sap;
2460114987Speter	int error;
2461114987Speter
2462114987Speter	if (uap->act) {
2463114987Speter		error = copyin(uap->act, &s32, sizeof(s32));
2464114987Speter		if (error)
2465114987Speter			return (error);
2466114987Speter		sa.sa_handler = PTRIN(s32.sa_u);
2467114987Speter		CP(s32, sa, sa_flags);
2468114987Speter		CP(s32, sa, sa_mask);
2469114987Speter		sap = &sa;
2470114987Speter	} else
2471114987Speter		sap = NULL;
2472114987Speter	error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
2473146583Sps	if (error == 0 && uap->oact != NULL) {
2474114987Speter		s32.sa_u = PTROUT(osa.sa_handler);
2475114987Speter		CP(osa, s32, sa_flags);
2476114987Speter		CP(osa, s32, sa_mask);
2477114987Speter		error = copyout(&s32, uap->oact, sizeof(s32));
2478114987Speter	}
2479114987Speter	return (error);
2480114987Speter}
2481114987Speter#endif
2482114987Speter
2483151582Sps#ifdef COMPAT_43
2484151720Speterstruct osigaction32 {
2485151582Sps	u_int32_t	sa_u;
2486151582Sps	osigset_t	sa_mask;
2487151582Sps	int		sa_flags;
2488151582Sps};
2489151582Sps
2490151582Sps#define	ONSIG	32
2491151582Sps
2492140481Spsint
2493151720Speterofreebsd32_sigaction(struct thread *td,
2494151720Speter			     struct ofreebsd32_sigaction_args *uap)
2495151582Sps{
2496151720Speter	struct osigaction32 s32;
2497151582Sps	struct sigaction sa, osa, *sap;
2498151582Sps	int error;
2499151582Sps
2500151582Sps	if (uap->signum <= 0 || uap->signum >= ONSIG)
2501151582Sps		return (EINVAL);
2502151582Sps
2503151582Sps	if (uap->nsa) {
2504151582Sps		error = copyin(uap->nsa, &s32, sizeof(s32));
2505151582Sps		if (error)
2506151582Sps			return (error);
2507151582Sps		sa.sa_handler = PTRIN(s32.sa_u);
2508151582Sps		CP(s32, sa, sa_flags);
2509151582Sps		OSIG2SIG(s32.sa_mask, sa.sa_mask);
2510151582Sps		sap = &sa;
2511151582Sps	} else
2512151582Sps		sap = NULL;
2513151582Sps	error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
2514151582Sps	if (error == 0 && uap->osa != NULL) {
2515151582Sps		s32.sa_u = PTROUT(osa.sa_handler);
2516151582Sps		CP(osa, s32, sa_flags);
2517151582Sps		SIG2OSIG(osa.sa_mask, s32.sa_mask);
2518151582Sps		error = copyout(&s32, uap->osa, sizeof(s32));
2519151582Sps	}
2520151582Sps	return (error);
2521151582Sps}
2522151582Sps
2523151582Spsint
2524151720Speterofreebsd32_sigprocmask(struct thread *td,
2525151720Speter			       struct ofreebsd32_sigprocmask_args *uap)
2526151582Sps{
2527151582Sps	sigset_t set, oset;
2528151582Sps	int error;
2529151582Sps
2530151582Sps	OSIG2SIG(uap->mask, set);
2531198507Skib	error = kern_sigprocmask(td, uap->how, &set, &oset, SIGPROCMASK_OLD);
2532151582Sps	SIG2OSIG(oset, td->td_retval[0]);
2533151582Sps	return (error);
2534151582Sps}
2535151582Sps
2536151582Spsint
2537151720Speterofreebsd32_sigpending(struct thread *td,
2538151720Speter			      struct ofreebsd32_sigpending_args *uap)
2539151582Sps{
2540151582Sps	struct proc *p = td->td_proc;
2541151582Sps	sigset_t siglist;
2542151582Sps
2543151582Sps	PROC_LOCK(p);
2544151582Sps	siglist = p->p_siglist;
2545151582Sps	SIGSETOR(siglist, td->td_siglist);
2546151582Sps	PROC_UNLOCK(p);
2547151582Sps	SIG2OSIG(siglist, td->td_retval[0]);
2548151582Sps	return (0);
2549151582Sps}
2550151582Sps
2551151582Spsstruct sigvec32 {
2552151582Sps	u_int32_t	sv_handler;
2553151582Sps	int		sv_mask;
2554151582Sps	int		sv_flags;
2555151582Sps};
2556151582Sps
2557151582Spsint
2558151720Speterofreebsd32_sigvec(struct thread *td,
2559151720Speter			  struct ofreebsd32_sigvec_args *uap)
2560151582Sps{
2561151582Sps	struct sigvec32 vec;
2562151582Sps	struct sigaction sa, osa, *sap;
2563151582Sps	int error;
2564151582Sps
2565151582Sps	if (uap->signum <= 0 || uap->signum >= ONSIG)
2566151582Sps		return (EINVAL);
2567151582Sps
2568151582Sps	if (uap->nsv) {
2569151582Sps		error = copyin(uap->nsv, &vec, sizeof(vec));
2570151582Sps		if (error)
2571151582Sps			return (error);
2572151582Sps		sa.sa_handler = PTRIN(vec.sv_handler);
2573151582Sps		OSIG2SIG(vec.sv_mask, sa.sa_mask);
2574151582Sps		sa.sa_flags = vec.sv_flags;
2575151582Sps		sa.sa_flags ^= SA_RESTART;
2576151582Sps		sap = &sa;
2577151582Sps	} else
2578151582Sps		sap = NULL;
2579151582Sps	error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
2580151582Sps	if (error == 0 && uap->osv != NULL) {
2581151582Sps		vec.sv_handler = PTROUT(osa.sa_handler);
2582151582Sps		SIG2OSIG(osa.sa_mask, vec.sv_mask);
2583151582Sps		vec.sv_flags = osa.sa_flags;
2584151582Sps		vec.sv_flags &= ~SA_NOCLDWAIT;
2585151582Sps		vec.sv_flags ^= SA_RESTART;
2586151582Sps		error = copyout(&vec, uap->osv, sizeof(vec));
2587151582Sps	}
2588151582Sps	return (error);
2589151582Sps}
2590151582Sps
2591151582Spsint
2592151720Speterofreebsd32_sigblock(struct thread *td,
2593151720Speter			    struct ofreebsd32_sigblock_args *uap)
2594151582Sps{
2595198507Skib	sigset_t set, oset;
2596151582Sps
2597151582Sps	OSIG2SIG(uap->mask, set);
2598198507Skib	kern_sigprocmask(td, SIG_BLOCK, &set, &oset, 0);
2599198507Skib	SIG2OSIG(oset, td->td_retval[0]);
2600151582Sps	return (0);
2601151582Sps}
2602151582Sps
2603151582Spsint
2604151720Speterofreebsd32_sigsetmask(struct thread *td,
2605151720Speter			      struct ofreebsd32_sigsetmask_args *uap)
2606151582Sps{
2607198507Skib	sigset_t set, oset;
2608151582Sps
2609151582Sps	OSIG2SIG(uap->mask, set);
2610198507Skib	kern_sigprocmask(td, SIG_SETMASK, &set, &oset, 0);
2611198507Skib	SIG2OSIG(oset, td->td_retval[0]);
2612151582Sps	return (0);
2613151582Sps}
2614151582Sps
2615151582Spsint
2616151720Speterofreebsd32_sigsuspend(struct thread *td,
2617151720Speter			      struct ofreebsd32_sigsuspend_args *uap)
2618151582Sps{
2619151582Sps	sigset_t mask;
2620151582Sps
2621151582Sps	OSIG2SIG(uap->mask, mask);
2622198506Skib	return (kern_sigsuspend(td, mask));
2623151582Sps}
2624151582Sps
2625151582Spsstruct sigstack32 {
2626151582Sps	u_int32_t	ss_sp;
2627151582Sps	int		ss_onstack;
2628151582Sps};
2629151582Sps
2630151582Spsint
2631151720Speterofreebsd32_sigstack(struct thread *td,
2632151720Speter			    struct ofreebsd32_sigstack_args *uap)
2633151582Sps{
2634151582Sps	struct sigstack32 s32;
2635151582Sps	struct sigstack nss, oss;
2636170870Smjacob	int error = 0, unss;
2637151582Sps
2638151582Sps	if (uap->nss != NULL) {
2639151582Sps		error = copyin(uap->nss, &s32, sizeof(s32));
2640151582Sps		if (error)
2641151582Sps			return (error);
2642151582Sps		nss.ss_sp = PTRIN(s32.ss_sp);
2643151582Sps		CP(s32, nss, ss_onstack);
2644170870Smjacob		unss = 1;
2645170870Smjacob	} else {
2646170870Smjacob		unss = 0;
2647151582Sps	}
2648151582Sps	oss.ss_sp = td->td_sigstk.ss_sp;
2649151582Sps	oss.ss_onstack = sigonstack(cpu_getstack(td));
2650170870Smjacob	if (unss) {
2651151582Sps		td->td_sigstk.ss_sp = nss.ss_sp;
2652151582Sps		td->td_sigstk.ss_size = 0;
2653170870Smjacob		td->td_sigstk.ss_flags |= (nss.ss_onstack & SS_ONSTACK);
2654151582Sps		td->td_pflags |= TDP_ALTSTACK;
2655151582Sps	}
2656151582Sps	if (uap->oss != NULL) {
2657151582Sps		s32.ss_sp = PTROUT(oss.ss_sp);
2658151582Sps		CP(oss, s32, ss_onstack);
2659151582Sps		error = copyout(&s32, uap->oss, sizeof(s32));
2660151582Sps	}
2661151582Sps	return (error);
2662151582Sps}
2663151582Sps#endif
2664151582Sps
2665151582Spsint
2666140481Spsfreebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
2667140481Sps{
2668140481Sps	struct timespec32 rmt32, rqt32;
2669140481Sps	struct timespec rmt, rqt;
2670140481Sps	int error;
2671140481Sps
2672151355Sps	error = copyin(uap->rqtp, &rqt32, sizeof(rqt32));
2673140481Sps	if (error)
2674140481Sps		return (error);
2675140481Sps
2676140481Sps	CP(rqt32, rqt, tv_sec);
2677140481Sps	CP(rqt32, rqt, tv_nsec);
2678140481Sps
2679140481Sps	if (uap->rmtp &&
2680140481Sps	    !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
2681140481Sps		return (EFAULT);
2682140481Sps	error = kern_nanosleep(td, &rqt, &rmt);
2683140481Sps	if (error && uap->rmtp) {
2684140481Sps		int error2;
2685140481Sps
2686140481Sps		CP(rmt, rmt32, tv_sec);
2687140481Sps		CP(rmt, rmt32, tv_nsec);
2688140481Sps
2689151355Sps		error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt32));
2690140481Sps		if (error2)
2691140481Sps			error = error2;
2692140481Sps	}
2693140481Sps	return (error);
2694140481Sps}
2695140481Sps
2696151357Spsint
2697151357Spsfreebsd32_clock_gettime(struct thread *td,
2698151357Sps			struct freebsd32_clock_gettime_args *uap)
2699151357Sps{
2700151357Sps	struct timespec	ats;
2701151357Sps	struct timespec32 ats32;
2702151357Sps	int error;
2703151357Sps
2704151357Sps	error = kern_clock_gettime(td, uap->clock_id, &ats);
2705151357Sps	if (error == 0) {
2706151357Sps		CP(ats, ats32, tv_sec);
2707151357Sps		CP(ats, ats32, tv_nsec);
2708151357Sps		error = copyout(&ats32, uap->tp, sizeof(ats32));
2709151357Sps	}
2710151357Sps	return (error);
2711151357Sps}
2712151357Sps
2713151357Spsint
2714151357Spsfreebsd32_clock_settime(struct thread *td,
2715151357Sps			struct freebsd32_clock_settime_args *uap)
2716151357Sps{
2717151357Sps	struct timespec	ats;
2718151357Sps	struct timespec32 ats32;
2719151357Sps	int error;
2720151357Sps
2721151357Sps	error = copyin(uap->tp, &ats32, sizeof(ats32));
2722151357Sps	if (error)
2723151357Sps		return (error);
2724151357Sps	CP(ats32, ats, tv_sec);
2725151357Sps	CP(ats32, ats, tv_nsec);
2726151357Sps
2727151357Sps	return (kern_clock_settime(td, uap->clock_id, &ats));
2728151357Sps}
2729151357Sps
2730151357Spsint
2731151357Spsfreebsd32_clock_getres(struct thread *td,
2732151357Sps		       struct freebsd32_clock_getres_args *uap)
2733151357Sps{
2734151357Sps	struct timespec	ts;
2735151357Sps	struct timespec32 ts32;
2736151357Sps	int error;
2737151357Sps
2738151357Sps	if (uap->tp == NULL)
2739151357Sps		return (0);
2740151357Sps	error = kern_clock_getres(td, uap->clock_id, &ts);
2741151357Sps	if (error == 0) {
2742151357Sps		CP(ts, ts32, tv_sec);
2743151357Sps		CP(ts, ts32, tv_nsec);
2744151357Sps		error = copyout(&ts32, uap->tp, sizeof(ts32));
2745151357Sps	}
2746151357Sps	return (error);
2747151357Sps}
2748151357Sps
2749162551Sdavidxuint
2750162551Sdavidxufreebsd32_thr_new(struct thread *td,
2751162551Sdavidxu		  struct freebsd32_thr_new_args *uap)
2752162551Sdavidxu{
2753162551Sdavidxu	struct thr_param32 param32;
2754162551Sdavidxu	struct thr_param param;
2755162551Sdavidxu	int error;
2756162551Sdavidxu
2757162551Sdavidxu	if (uap->param_size < 0 ||
2758162551Sdavidxu	    uap->param_size > sizeof(struct thr_param32))
2759162551Sdavidxu		return (EINVAL);
2760162551Sdavidxu	bzero(&param, sizeof(struct thr_param));
2761162551Sdavidxu	bzero(&param32, sizeof(struct thr_param32));
2762162551Sdavidxu	error = copyin(uap->param, &param32, uap->param_size);
2763162551Sdavidxu	if (error != 0)
2764162551Sdavidxu		return (error);
2765162551Sdavidxu	param.start_func = PTRIN(param32.start_func);
2766162551Sdavidxu	param.arg = PTRIN(param32.arg);
2767162551Sdavidxu	param.stack_base = PTRIN(param32.stack_base);
2768162551Sdavidxu	param.stack_size = param32.stack_size;
2769162551Sdavidxu	param.tls_base = PTRIN(param32.tls_base);
2770162551Sdavidxu	param.tls_size = param32.tls_size;
2771162551Sdavidxu	param.child_tid = PTRIN(param32.child_tid);
2772162551Sdavidxu	param.parent_tid = PTRIN(param32.parent_tid);
2773162551Sdavidxu	param.flags = param32.flags;
2774162551Sdavidxu	param.rtp = PTRIN(param32.rtp);
2775162551Sdavidxu	param.spare[0] = PTRIN(param32.spare[0]);
2776162551Sdavidxu	param.spare[1] = PTRIN(param32.spare[1]);
2777162551Sdavidxu	param.spare[2] = PTRIN(param32.spare[2]);
2778162551Sdavidxu
2779162551Sdavidxu	return (kern_thr_new(td, &param));
2780162551Sdavidxu}
2781162551Sdavidxu
2782162551Sdavidxuint
2783162551Sdavidxufreebsd32_thr_suspend(struct thread *td, struct freebsd32_thr_suspend_args *uap)
2784162551Sdavidxu{
2785162551Sdavidxu	struct timespec32 ts32;
2786162551Sdavidxu	struct timespec ts, *tsp;
2787162551Sdavidxu	int error;
2788162551Sdavidxu
2789162551Sdavidxu	error = 0;
2790162551Sdavidxu	tsp = NULL;
2791162551Sdavidxu	if (uap->timeout != NULL) {
2792162551Sdavidxu		error = copyin((const void *)uap->timeout, (void *)&ts32,
2793162551Sdavidxu		    sizeof(struct timespec32));
2794162551Sdavidxu		if (error != 0)
2795162551Sdavidxu			return (error);
2796162551Sdavidxu		ts.tv_sec = ts32.tv_sec;
2797162551Sdavidxu		ts.tv_nsec = ts32.tv_nsec;
2798162551Sdavidxu		tsp = &ts;
2799162551Sdavidxu	}
2800162551Sdavidxu	return (kern_thr_suspend(td, tsp));
2801162551Sdavidxu}
2802162551Sdavidxu
2803163018Sdavidxuvoid
2804163018Sdavidxusiginfo_to_siginfo32(siginfo_t *src, struct siginfo32 *dst)
2805163018Sdavidxu{
2806163018Sdavidxu	bzero(dst, sizeof(*dst));
2807163018Sdavidxu	dst->si_signo = src->si_signo;
2808163018Sdavidxu	dst->si_errno = src->si_errno;
2809163018Sdavidxu	dst->si_code = src->si_code;
2810163018Sdavidxu	dst->si_pid = src->si_pid;
2811163018Sdavidxu	dst->si_uid = src->si_uid;
2812163018Sdavidxu	dst->si_status = src->si_status;
2813184829Speter	dst->si_addr = (uintptr_t)src->si_addr;
2814163018Sdavidxu	dst->si_value.sigval_int = src->si_value.sival_int;
2815163018Sdavidxu	dst->si_timerid = src->si_timerid;
2816163018Sdavidxu	dst->si_overrun = src->si_overrun;
2817163018Sdavidxu}
2818163018Sdavidxu
2819163018Sdavidxuint
2820163018Sdavidxufreebsd32_sigtimedwait(struct thread *td, struct freebsd32_sigtimedwait_args *uap)
2821163018Sdavidxu{
2822163018Sdavidxu	struct timespec32 ts32;
2823163018Sdavidxu	struct timespec ts;
2824163018Sdavidxu	struct timespec *timeout;
2825163018Sdavidxu	sigset_t set;
2826163018Sdavidxu	ksiginfo_t ksi;
2827163018Sdavidxu	struct siginfo32 si32;
2828163018Sdavidxu	int error;
2829163018Sdavidxu
2830163018Sdavidxu	if (uap->timeout) {
2831163018Sdavidxu		error = copyin(uap->timeout, &ts32, sizeof(ts32));
2832163018Sdavidxu		if (error)
2833163018Sdavidxu			return (error);
2834163018Sdavidxu		ts.tv_sec = ts32.tv_sec;
2835163018Sdavidxu		ts.tv_nsec = ts32.tv_nsec;
2836163018Sdavidxu		timeout = &ts;
2837163018Sdavidxu	} else
2838163018Sdavidxu		timeout = NULL;
2839163018Sdavidxu
2840163018Sdavidxu	error = copyin(uap->set, &set, sizeof(set));
2841163018Sdavidxu	if (error)
2842163018Sdavidxu		return (error);
2843163018Sdavidxu
2844163018Sdavidxu	error = kern_sigtimedwait(td, set, &ksi, timeout);
2845163018Sdavidxu	if (error)
2846163018Sdavidxu		return (error);
2847163018Sdavidxu
2848163018Sdavidxu	if (uap->info) {
2849163018Sdavidxu		siginfo_to_siginfo32(&ksi.ksi_info, &si32);
2850163018Sdavidxu		error = copyout(&si32, uap->info, sizeof(struct siginfo32));
2851163018Sdavidxu	}
2852163018Sdavidxu
2853163018Sdavidxu	if (error == 0)
2854163018Sdavidxu		td->td_retval[0] = ksi.ksi_signo;
2855163018Sdavidxu	return (error);
2856163018Sdavidxu}
2857163018Sdavidxu
2858163018Sdavidxu/*
2859163018Sdavidxu * MPSAFE
2860163018Sdavidxu */
2861163018Sdavidxuint
2862163018Sdavidxufreebsd32_sigwaitinfo(struct thread *td, struct freebsd32_sigwaitinfo_args *uap)
2863163018Sdavidxu{
2864163018Sdavidxu	ksiginfo_t ksi;
2865163018Sdavidxu	struct siginfo32 si32;
2866163018Sdavidxu	sigset_t set;
2867163018Sdavidxu	int error;
2868163018Sdavidxu
2869163018Sdavidxu	error = copyin(uap->set, &set, sizeof(set));
2870163018Sdavidxu	if (error)
2871163018Sdavidxu		return (error);
2872163018Sdavidxu
2873163018Sdavidxu	error = kern_sigtimedwait(td, set, &ksi, NULL);
2874163018Sdavidxu	if (error)
2875163018Sdavidxu		return (error);
2876163018Sdavidxu
2877163018Sdavidxu	if (uap->info) {
2878163018Sdavidxu		siginfo_to_siginfo32(&ksi.ksi_info, &si32);
2879163018Sdavidxu		error = copyout(&si32, uap->info, sizeof(struct siginfo32));
2880163018Sdavidxu	}
2881163018Sdavidxu	if (error == 0)
2882163018Sdavidxu		td->td_retval[0] = ksi.ksi_signo;
2883163018Sdavidxu	return (error);
2884163018Sdavidxu}
2885163018Sdavidxu
2886180433Sbrooksint
2887180433Sbrooksfreebsd32_cpuset_setid(struct thread *td,
2888180433Sbrooks    struct freebsd32_cpuset_setid_args *uap)
2889180433Sbrooks{
2890180433Sbrooks	struct cpuset_setid_args ap;
2891180433Sbrooks
2892180433Sbrooks	ap.which = uap->which;
2893205014Snwhitehorn	ap.id = PAIR32TO64(id_t,uap->id);
2894180433Sbrooks	ap.setid = uap->setid;
2895180433Sbrooks
2896180436Sbrooks	return (cpuset_setid(td, &ap));
2897180433Sbrooks}
2898180433Sbrooks
2899180433Sbrooksint
2900180433Sbrooksfreebsd32_cpuset_getid(struct thread *td,
2901180433Sbrooks    struct freebsd32_cpuset_getid_args *uap)
2902180433Sbrooks{
2903180433Sbrooks	struct cpuset_getid_args ap;
2904180433Sbrooks
2905180433Sbrooks	ap.level = uap->level;
2906180433Sbrooks	ap.which = uap->which;
2907205014Snwhitehorn	ap.id = PAIR32TO64(id_t,uap->id);
2908180433Sbrooks	ap.setid = uap->setid;
2909180433Sbrooks
2910180436Sbrooks	return (cpuset_getid(td, &ap));
2911180433Sbrooks}
2912180433Sbrooks
2913180433Sbrooksint
2914180433Sbrooksfreebsd32_cpuset_getaffinity(struct thread *td,
2915180433Sbrooks    struct freebsd32_cpuset_getaffinity_args *uap)
2916180433Sbrooks{
2917180433Sbrooks	struct cpuset_getaffinity_args ap;
2918180433Sbrooks
2919180433Sbrooks	ap.level = uap->level;
2920180433Sbrooks	ap.which = uap->which;
2921205014Snwhitehorn	ap.id = PAIR32TO64(id_t,uap->id);
2922180433Sbrooks	ap.cpusetsize = uap->cpusetsize;
2923180433Sbrooks	ap.mask = uap->mask;
2924180433Sbrooks
2925180436Sbrooks	return (cpuset_getaffinity(td, &ap));
2926180433Sbrooks}
2927180433Sbrooks
2928180433Sbrooksint
2929180433Sbrooksfreebsd32_cpuset_setaffinity(struct thread *td,
2930180433Sbrooks    struct freebsd32_cpuset_setaffinity_args *uap)
2931180433Sbrooks{
2932180433Sbrooks	struct cpuset_setaffinity_args ap;
2933180433Sbrooks
2934180433Sbrooks	ap.level = uap->level;
2935180433Sbrooks	ap.which = uap->which;
2936205014Snwhitehorn	ap.id = PAIR32TO64(id_t,uap->id);
2937180433Sbrooks	ap.cpusetsize = uap->cpusetsize;
2938180433Sbrooks	ap.mask = uap->mask;
2939180433Sbrooks
2940180436Sbrooks	return (cpuset_setaffinity(td, &ap));
2941180433Sbrooks}
2942180433Sbrooks
2943183188Sobrienint
2944183188Sobrienfreebsd32_nmount(struct thread *td,
2945183188Sobrien    struct freebsd32_nmount_args /* {
2946183188Sobrien    	struct iovec *iovp;
2947183188Sobrien    	unsigned int iovcnt;
2948183188Sobrien    	int flags;
2949183188Sobrien    } */ *uap)
2950183188Sobrien{
2951183188Sobrien	struct uio *auio;
2952189290Sjamie	int error;
2953183188Sobrien
2954195104Srwatson	AUDIT_ARG_FFLAGS(uap->flags);
2955183188Sobrien
2956183188Sobrien	/*
2957183188Sobrien	 * Filter out MNT_ROOTFS.  We do not want clients of nmount() in
2958183188Sobrien	 * userspace to set this flag, but we must filter it out if we want
2959183188Sobrien	 * MNT_UPDATE on the root file system to work.
2960183188Sobrien	 * MNT_ROOTFS should only be set in the kernel in vfs_mountroot_try().
2961183188Sobrien	 */
2962183188Sobrien	uap->flags &= ~MNT_ROOTFS;
2963183188Sobrien
2964183188Sobrien	/*
2965183188Sobrien	 * check that we have an even number of iovec's
2966183188Sobrien	 * and that we have at least two options.
2967183188Sobrien	 */
2968183188Sobrien	if ((uap->iovcnt & 1) || (uap->iovcnt < 4))
2969183188Sobrien		return (EINVAL);
2970183188Sobrien
2971183188Sobrien	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
2972183188Sobrien	if (error)
2973183188Sobrien		return (error);
2974189290Sjamie	error = vfs_donmount(td, uap->flags, auio);
2975183188Sobrien
2976183188Sobrien	free(auio, M_IOV);
2977183188Sobrien	return error;
2978183188Sobrien}
2979183188Sobrien
2980100384Speter#if 0
2981100384Speterint
2982119333Speterfreebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
2983100384Speter{
2984100384Speter	struct yyy32 *p32, s32;
2985100384Speter	struct yyy *p = NULL, s;
2986183044Sobrien	struct xxx_arg ap;
2987183044Sobrien	int error;
2988100384Speter
2989147654Sjhb	if (uap->zzz) {
2990147654Sjhb		error = copyin(uap->zzz, &s32, sizeof(s32));
2991100384Speter		if (error)
2992100384Speter			return (error);
2993100384Speter		/* translate in */
2994147654Sjhb		p = &s;
2995100384Speter	}
2996147654Sjhb	error = kern_xxx(td, p);
2997100384Speter	if (error)
2998100384Speter		return (error);
2999147654Sjhb	if (uap->zzz) {
3000100384Speter		/* translate out */
3001100384Speter		error = copyout(&s32, p32, sizeof(s32));
3002100384Speter	}
3003100384Speter	return (error);
3004100384Speter}
3005100384Speter#endif
3006183365Sjhb
3007183365Sjhbint
3008183365Sjhbsyscall32_register(int *offset, struct sysent *new_sysent,
3009183365Sjhb    struct sysent *old_sysent)
3010183365Sjhb{
3011183365Sjhb	if (*offset == NO_SYSCALL) {
3012183365Sjhb		int i;
3013183365Sjhb
3014183365Sjhb		for (i = 1; i < SYS_MAXSYSCALL; ++i)
3015183365Sjhb			if (freebsd32_sysent[i].sy_call ==
3016183365Sjhb			    (sy_call_t *)lkmnosys)
3017183365Sjhb				break;
3018183365Sjhb		if (i == SYS_MAXSYSCALL)
3019183365Sjhb			return (ENFILE);
3020183365Sjhb		*offset = i;
3021183365Sjhb	} else if (*offset < 0 || *offset >= SYS_MAXSYSCALL)
3022183365Sjhb		return (EINVAL);
3023183365Sjhb	else if (freebsd32_sysent[*offset].sy_call != (sy_call_t *)lkmnosys &&
3024183365Sjhb	    freebsd32_sysent[*offset].sy_call != (sy_call_t *)lkmressys)
3025183365Sjhb		return (EEXIST);
3026183365Sjhb
3027183365Sjhb	*old_sysent = freebsd32_sysent[*offset];
3028183365Sjhb	freebsd32_sysent[*offset] = *new_sysent;
3029183365Sjhb	return 0;
3030183365Sjhb}
3031183365Sjhb
3032183365Sjhbint
3033183365Sjhbsyscall32_deregister(int *offset, struct sysent *old_sysent)
3034183365Sjhb{
3035183365Sjhb
3036183365Sjhb	if (*offset)
3037183365Sjhb		freebsd32_sysent[*offset] = *old_sysent;
3038183365Sjhb	return 0;
3039183365Sjhb}
3040183365Sjhb
3041183365Sjhbint
3042183365Sjhbsyscall32_module_handler(struct module *mod, int what, void *arg)
3043183365Sjhb{
3044183365Sjhb	struct syscall_module_data *data = (struct syscall_module_data*)arg;
3045183365Sjhb	modspecific_t ms;
3046183365Sjhb	int error;
3047183365Sjhb
3048183365Sjhb	switch (what) {
3049183365Sjhb	case MOD_LOAD:
3050183365Sjhb		error = syscall32_register(data->offset, data->new_sysent,
3051183365Sjhb		    &data->old_sysent);
3052183365Sjhb		if (error) {
3053183365Sjhb			/* Leave a mark so we know to safely unload below. */
3054183365Sjhb			data->offset = NULL;
3055183365Sjhb			return error;
3056183365Sjhb		}
3057183365Sjhb		ms.intval = *data->offset;
3058183365Sjhb		MOD_XLOCK;
3059183365Sjhb		module_setspecific(mod, &ms);
3060183365Sjhb		MOD_XUNLOCK;
3061183365Sjhb		if (data->chainevh)
3062183365Sjhb			error = data->chainevh(mod, what, data->chainarg);
3063183365Sjhb		return (error);
3064183365Sjhb	case MOD_UNLOAD:
3065183365Sjhb		/*
3066183365Sjhb		 * MOD_LOAD failed, so just return without calling the
3067183365Sjhb		 * chained handler since we didn't pass along the MOD_LOAD
3068183365Sjhb		 * event.
3069183365Sjhb		 */
3070183365Sjhb		if (data->offset == NULL)
3071183365Sjhb			return (0);
3072183365Sjhb		if (data->chainevh) {
3073183365Sjhb			error = data->chainevh(mod, what, data->chainarg);
3074183365Sjhb			if (error)
3075183365Sjhb				return (error);
3076183365Sjhb		}
3077185589Sjhb		error = syscall32_deregister(data->offset, &data->old_sysent);
3078183365Sjhb		return (error);
3079183365Sjhb	default:
3080183365Sjhb		error = EOPNOTSUPP;
3081183365Sjhb		if (data->chainevh)
3082183365Sjhb			error = data->chainevh(mod, what, data->chainarg);
3083183365Sjhb		return (error);
3084183365Sjhb	}
3085183365Sjhb}
3086205014Snwhitehorn
3087205014Snwhitehornregister_t *
3088205014Snwhitehornfreebsd32_copyout_strings(struct image_params *imgp)
3089205014Snwhitehorn{
3090205014Snwhitehorn	int argc, envc;
3091205014Snwhitehorn	u_int32_t *vectp;
3092205014Snwhitehorn	char *stringp, *destp;
3093205014Snwhitehorn	u_int32_t *stack_base;
3094205014Snwhitehorn	struct freebsd32_ps_strings *arginfo;
3095205014Snwhitehorn	size_t execpath_len;
3096205014Snwhitehorn	int szsigcode;
3097205014Snwhitehorn
3098205014Snwhitehorn	/*
3099205014Snwhitehorn	 * Calculate string base and vector table pointers.
3100205014Snwhitehorn	 * Also deal with signal trampoline code for this exec type.
3101205014Snwhitehorn	 */
3102205014Snwhitehorn	if (imgp->execpath != NULL && imgp->auxargs != NULL)
3103205014Snwhitehorn		execpath_len = strlen(imgp->execpath) + 1;
3104205014Snwhitehorn	else
3105205014Snwhitehorn		execpath_len = 0;
3106205014Snwhitehorn	arginfo = (struct freebsd32_ps_strings *)FREEBSD32_PS_STRINGS;
3107205014Snwhitehorn	szsigcode = *(imgp->proc->p_sysent->sv_szsigcode);
3108205014Snwhitehorn	destp =	(caddr_t)arginfo - szsigcode - SPARE_USRSPACE -
3109205014Snwhitehorn		roundup(execpath_len, sizeof(char *)) -
3110205014Snwhitehorn		roundup((ARG_MAX - imgp->args->stringspace), sizeof(char *));
3111205014Snwhitehorn
3112205014Snwhitehorn	/*
3113205014Snwhitehorn	 * install sigcode
3114205014Snwhitehorn	 */
3115205014Snwhitehorn	if (szsigcode)
3116205014Snwhitehorn		copyout(imgp->proc->p_sysent->sv_sigcode,
3117205014Snwhitehorn			((caddr_t)arginfo - szsigcode), szsigcode);
3118205014Snwhitehorn
3119205014Snwhitehorn	/*
3120205014Snwhitehorn	 * Copy the image path for the rtld.
3121205014Snwhitehorn	 */
3122205014Snwhitehorn	if (execpath_len != 0) {
3123205014Snwhitehorn		imgp->execpathp = (uintptr_t)arginfo - szsigcode - execpath_len;
3124205014Snwhitehorn		copyout(imgp->execpath, (void *)imgp->execpathp,
3125205014Snwhitehorn		    execpath_len);
3126205014Snwhitehorn	}
3127205014Snwhitehorn
3128205014Snwhitehorn	/*
3129205014Snwhitehorn	 * If we have a valid auxargs ptr, prepare some room
3130205014Snwhitehorn	 * on the stack.
3131205014Snwhitehorn	 */
3132205014Snwhitehorn	if (imgp->auxargs) {
3133205014Snwhitehorn		/*
3134205014Snwhitehorn		 * 'AT_COUNT*2' is size for the ELF Auxargs data. This is for
3135205014Snwhitehorn		 * lower compatibility.
3136205014Snwhitehorn		 */
3137205014Snwhitehorn		imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size
3138205014Snwhitehorn			: (AT_COUNT * 2);
3139205014Snwhitehorn		/*
3140205014Snwhitehorn		 * The '+ 2' is for the null pointers at the end of each of
3141205014Snwhitehorn		 * the arg and env vector sets,and imgp->auxarg_size is room
3142205014Snwhitehorn		 * for argument of Runtime loader.
3143205014Snwhitehorn		 */
3144205014Snwhitehorn		vectp = (u_int32_t *) (destp - (imgp->args->argc +
3145205014Snwhitehorn		    imgp->args->envc + 2 + imgp->auxarg_size + execpath_len) *
3146205014Snwhitehorn		    sizeof(u_int32_t));
3147205014Snwhitehorn	} else
3148205014Snwhitehorn		/*
3149205014Snwhitehorn		 * The '+ 2' is for the null pointers at the end of each of
3150205014Snwhitehorn		 * the arg and env vector sets
3151205014Snwhitehorn		 */
3152205014Snwhitehorn		vectp = (u_int32_t *)
3153205014Snwhitehorn			(destp - (imgp->args->argc + imgp->args->envc + 2) * sizeof(u_int32_t));
3154205014Snwhitehorn
3155205014Snwhitehorn	/*
3156205014Snwhitehorn	 * vectp also becomes our initial stack base
3157205014Snwhitehorn	 */
3158205014Snwhitehorn	stack_base = vectp;
3159205014Snwhitehorn
3160205014Snwhitehorn	stringp = imgp->args->begin_argv;
3161205014Snwhitehorn	argc = imgp->args->argc;
3162205014Snwhitehorn	envc = imgp->args->envc;
3163205014Snwhitehorn	/*
3164205014Snwhitehorn	 * Copy out strings - arguments and environment.
3165205014Snwhitehorn	 */
3166205014Snwhitehorn	copyout(stringp, destp, ARG_MAX - imgp->args->stringspace);
3167205014Snwhitehorn
3168205014Snwhitehorn	/*
3169205014Snwhitehorn	 * Fill in "ps_strings" struct for ps, w, etc.
3170205014Snwhitehorn	 */
3171205014Snwhitehorn	suword32(&arginfo->ps_argvstr, (u_int32_t)(intptr_t)vectp);
3172205014Snwhitehorn	suword32(&arginfo->ps_nargvstr, argc);
3173205014Snwhitehorn
3174205014Snwhitehorn	/*
3175205014Snwhitehorn	 * Fill in argument portion of vector table.
3176205014Snwhitehorn	 */
3177205014Snwhitehorn	for (; argc > 0; --argc) {
3178205014Snwhitehorn		suword32(vectp++, (u_int32_t)(intptr_t)destp);
3179205014Snwhitehorn		while (*stringp++ != 0)
3180205014Snwhitehorn			destp++;
3181205014Snwhitehorn		destp++;
3182205014Snwhitehorn	}
3183205014Snwhitehorn
3184205014Snwhitehorn	/* a null vector table pointer separates the argp's from the envp's */
3185205014Snwhitehorn	suword32(vectp++, 0);
3186205014Snwhitehorn
3187205014Snwhitehorn	suword32(&arginfo->ps_envstr, (u_int32_t)(intptr_t)vectp);
3188205014Snwhitehorn	suword32(&arginfo->ps_nenvstr, envc);
3189205014Snwhitehorn
3190205014Snwhitehorn	/*
3191205014Snwhitehorn	 * Fill in environment portion of vector table.
3192205014Snwhitehorn	 */
3193205014Snwhitehorn	for (; envc > 0; --envc) {
3194205014Snwhitehorn		suword32(vectp++, (u_int32_t)(intptr_t)destp);
3195205014Snwhitehorn		while (*stringp++ != 0)
3196205014Snwhitehorn			destp++;
3197205014Snwhitehorn		destp++;
3198205014Snwhitehorn	}
3199205014Snwhitehorn
3200205014Snwhitehorn	/* end of vector table is a null pointer */
3201205014Snwhitehorn	suword32(vectp, 0);
3202205014Snwhitehorn
3203205014Snwhitehorn	return ((register_t *)stack_base);
3204205014Snwhitehorn}
3205205014Snwhitehorn
3206