aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Wemm <peter@FreeBSD.org>2002-07-20 02:56:12 +0000
committerPeter Wemm <peter@FreeBSD.org>2002-07-20 02:56:12 +0000
commit3ebc124838799d79bb81993028066939255edfbf (patch)
tree442882c197085f1177ad99039e6387b24c60e44a
parent382f95d332eb42a6a06ef585d2855b536978a48d (diff)
downloadsrc-3ebc124838799d79bb81993028066939255edfbf.tar.gz
src-3ebc124838799d79bb81993028066939255edfbf.zip
Infrastructure tweaks to allow having both an Elf32 and an Elf64 executable
handler in the kernel at the same time. Also, allow for the exec_new_vmspace() code to build a different sized vmspace depending on the executable environment. This is a big help for execing i386 binaries on ia64. The ELF exec code grows the ability to map partial pages when there is a page size difference, eg: emulating 4K pages on 8K or 16K hardware pages. Flesh out the i386 emulation support for ia64. At this point, the only binary that I know of that fails is cvsup, because the cvsup runtime tries to execute code in pages not marked executable. Obtained from: dfr (mostly, many tweaks from me).
Notes
Notes: svn path=/head/; revision=100384
-rw-r--r--sys/alpha/alpha/elf_machdep.c40
-rw-r--r--sys/alpha/linux/linux_sysvec.c10
-rw-r--r--sys/alpha/osf1/imgact_osf1.c2
-rw-r--r--sys/amd64/amd64/elf_machdep.c40
-rw-r--r--sys/amd64/ia32/ia32.h103
-rw-r--r--sys/amd64/ia32/ia32_misc.c1339
-rw-r--r--sys/amd64/ia32/ia32_sysvec.c365
-rw-r--r--sys/amd64/ia32/ia32_util.h94
-rw-r--r--sys/amd64/ia32/syscalls.master659
-rw-r--r--sys/compat/freebsd32/freebsd32.h103
-rw-r--r--sys/compat/freebsd32/freebsd32_misc.c1339
-rw-r--r--sys/compat/freebsd32/freebsd32_util.h94
-rw-r--r--sys/compat/freebsd32/syscalls.master659
-rw-r--r--sys/compat/ia32/ia32_sysvec.c365
-rw-r--r--sys/compat/ia32/ia32_util.h94
-rw-r--r--sys/compat/pecoff/imgact_pecoff.c2
-rw-r--r--sys/compat/svr4/imgact_svr4.c2
-rw-r--r--sys/compat/svr4/svr4_sysvec.c9
-rw-r--r--sys/conf/files4
-rw-r--r--sys/conf/files.ia643
-rw-r--r--sys/i386/i386/elf_machdep.c40
-rw-r--r--sys/i386/ibcs2/imgact_coff.c2
-rw-r--r--sys/i386/linux/imgact_linux.c2
-rw-r--r--sys/i386/linux/linux_sysvec.c10
-rw-r--r--sys/ia64/ia32/ia32.h103
-rw-r--r--sys/ia64/ia32/ia32_misc.c1339
-rw-r--r--sys/ia64/ia32/ia32_signal.c365
-rw-r--r--sys/ia64/ia32/ia32_sysvec.c365
-rw-r--r--sys/ia64/ia32/ia32_util.h94
-rw-r--r--sys/ia64/ia32/imgact_ia32.c1446
-rw-r--r--sys/ia64/ia32/imgact_ia32.h112
-rw-r--r--sys/ia64/ia32/syscalls.master659
-rw-r--r--sys/ia64/ia64/elf_machdep.c38
-rw-r--r--sys/ia64/include/elf.h17
-rw-r--r--sys/kern/imgact_aout.c2
-rw-r--r--sys/kern/imgact_elf.c455
-rw-r--r--sys/kern/imgact_elf32.c38
-rw-r--r--sys/kern/imgact_elf64.c38
-rw-r--r--sys/kern/imgact_elfN.c51
-rw-r--r--sys/kern/imgact_gzip.c2
-rw-r--r--sys/kern/init_main.c9
-rw-r--r--sys/kern/kern_exec.c29
-rw-r--r--sys/powerpc/powerpc/elf_machdep.c40
-rw-r--r--sys/sparc64/sparc64/elf_machdep.c40
-rw-r--r--sys/sys/elf_generic.h1
-rw-r--r--sys/sys/imgact.h3
-rw-r--r--sys/sys/imgact_elf.h24
-rw-r--r--sys/sys/sysent.h5
-rw-r--r--sys/vm/vm_extern.h2
-rw-r--r--sys/vm/vm_map.c5
50 files changed, 7922 insertions, 2740 deletions
diff --git a/sys/alpha/alpha/elf_machdep.c b/sys/alpha/alpha/elf_machdep.c
index ebd3b60d204c..8e443e7643e5 100644
--- a/sys/alpha/alpha/elf_machdep.c
+++ b/sys/alpha/alpha/elf_machdep.c
@@ -32,9 +32,47 @@
#include <sys/proc.h>
#include <sys/namei.h>
#include <sys/fcntl.h>
+#include <sys/sysent.h>
+#include <sys/imgact_elf.h>
+#include <sys/syscall.h>
+#include <sys/signalvar.h>
#include <sys/vnode.h>
#include <sys/linker.h>
#include <machine/elf.h>
+#include <machine/md_var.h>
+
+struct sysentvec elf64_freebsd_sysvec = {
+ SYS_MAXSYSCALL,
+ sysent,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ elf64_freebsd_fixup,
+ sendsig,
+ sigcode,
+ &szsigcode,
+ 0,
+ "FreeBSD ELF64",
+ __elfN(coredump),
+ NULL,
+ MINSIGSTKSZ
+};
+
+static Elf64_Brandinfo freebsd_brand_info = {
+ ELFOSABI_FREEBSD,
+ EM_ALPHA,
+ "FreeBSD",
+ "",
+ "/usr/libexec/ld-elf.so.1",
+ &elf64_freebsd_sysvec
+ };
+
+SYSINIT(elf64, SI_SUB_EXEC, SI_ORDER_ANY,
+ (sysinit_cfunc_t) elf64_insert_brand_entry,
+ &freebsd_brand_info);
/* Process one elf relocation with addend. */
int
@@ -85,7 +123,7 @@ elf_reloc(linker_file_t lf, const void *data, int type)
addr = elf_lookup(lf, symidx, 1);
if (addr == 0)
return -1;
- addr += addend;
+ addr += addend;
if (*where != addr)
*where = addr;
break;
diff --git a/sys/alpha/linux/linux_sysvec.c b/sys/alpha/linux/linux_sysvec.c
index bedb8bff637e..52af25f19301 100644
--- a/sys/alpha/linux/linux_sysvec.c
+++ b/sys/alpha/linux/linux_sysvec.c
@@ -189,13 +189,14 @@ struct sysentvec elf_linux_sysvec = {
&linux_szsigcode,
0,
"Linux ELF",
- elf_coredump,
+ elf64_coredump,
exec_linux_imgact_try,
LINUX_MINSIGSTKSZ
};
static Elf64_Brandinfo linux_brand = {
ELFOSABI_LINUX,
+ EM_ALPHA,
"Linux",
"/compat/linux",
"/lib/ld-linux.so.1",
@@ -204,6 +205,7 @@ static Elf64_Brandinfo linux_brand = {
static Elf64_Brandinfo linux_glibc2brand = {
ELFOSABI_LINUX,
+ EM_ALPHA,
"Linux",
"/compat/linux",
"/lib/ld-linux.so.2",
@@ -229,7 +231,7 @@ linux_elf_modevent(module_t mod, int type, void *data)
case MOD_LOAD:
for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL;
++brandinfo)
- if (elf_insert_brand_entry(*brandinfo) < 0)
+ if (elf64_insert_brand_entry(*brandinfo) < 0)
error = EINVAL;
if (error == 0) {
SET_FOREACH(lihp, linux_ioctl_handler_set)
@@ -242,12 +244,12 @@ linux_elf_modevent(module_t mod, int type, void *data)
case MOD_UNLOAD:
for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL;
++brandinfo)
- if (elf_brand_inuse(*brandinfo))
+ if (elf64_brand_inuse(*brandinfo))
error = EBUSY;
if (error == 0) {
for (brandinfo = &linux_brandlist[0];
*brandinfo != NULL; ++brandinfo)
- if (elf_remove_brand_entry(*brandinfo) < 0)
+ if (elf64_remove_brand_entry(*brandinfo) < 0)
error = EINVAL;
}
if (error == 0) {
diff --git a/sys/alpha/osf1/imgact_osf1.c b/sys/alpha/osf1/imgact_osf1.c
index b1e1da78980d..4eee3a7447a5 100644
--- a/sys/alpha/osf1/imgact_osf1.c
+++ b/sys/alpha/osf1/imgact_osf1.c
@@ -178,7 +178,7 @@ exec_osf1_imgact(struct image_params *imgp)
/*
* Destroy old process VM and create a new one (with a new stack).
*/
- exec_new_vmspace(imgp);
+ exec_new_vmspace(imgp, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS, USRSTACK);
/*
* The vm space can now be changed.
diff --git a/sys/amd64/amd64/elf_machdep.c b/sys/amd64/amd64/elf_machdep.c
index 96d91b00c04d..188d60e6529b 100644
--- a/sys/amd64/amd64/elf_machdep.c
+++ b/sys/amd64/amd64/elf_machdep.c
@@ -26,9 +26,49 @@
*/
#include <sys/param.h>
+#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/linker.h>
+#include <sys/sysent.h>
+#include <sys/imgact_elf.h>
+#include <sys/syscall.h>
+#include <sys/signalvar.h>
+#include <sys/vnode.h>
#include <machine/elf.h>
+#include <machine/md_var.h>
+
+struct sysentvec elf32_freebsd_sysvec = {
+ SYS_MAXSYSCALL,
+ sysent,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ elf32_freebsd_fixup,
+ sendsig,
+ sigcode,
+ &szsigcode,
+ 0,
+ "FreeBSD ELF32",
+ __elfN(coredump),
+ NULL,
+ MINSIGSTKSZ
+};
+
+static Elf32_Brandinfo freebsd_brand_info = {
+ ELFOSABI_FREEBSD,
+ EM_386,
+ "FreeBSD",
+ "",
+ "/usr/libexec/ld-elf.so.1",
+ &elf32_freebsd_sysvec
+ };
+
+SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_ANY,
+ (sysinit_cfunc_t) elf32_insert_brand_entry,
+ &freebsd_brand_info);
/* Process one elf relocation with addend. */
int
diff --git a/sys/amd64/ia32/ia32.h b/sys/amd64/ia32/ia32.h
new file mode 100644
index 000000000000..943b24c61ed3
--- /dev/null
+++ b/sys/amd64/ia32/ia32.h
@@ -0,0 +1,103 @@
+/*-
+ * Copyright (c) 2001 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _IA64_IA32_IA32_H_
+#define _IA64_IA32_IA32_H_
+
+#define PTRIN(v) (void *)(uintptr_t) (v)
+#define PTROUT(v) (u_int32_t)(uintptr_t) (v)
+
+#define CP(src,dst,fld) do { (dst).fld = (src).fld; } while (0)
+#define PTRIN_CP(src,dst,fld) \
+ do { (dst).fld = PTRIN((src).fld); } while (0)
+#define PTROUT_CP(src,dst,fld) \
+ do { (dst).fld = PTROUT((src).fld); } while (0)
+
+struct timeval32 {
+ int32_t tv_sec;
+ int32_t tv_usec;
+};
+#define TV_CP(src,dst,fld) do { \
+ CP((src).fld,(dst).fld,tv_sec); \
+ CP((src).fld,(dst).fld,tv_usec); \
+} while (0);
+
+struct timespec32 {
+ u_int32_t tv_sec;
+ u_int32_t tv_nsec;
+};
+#define TS_CP(src,dst,fld) do { \
+ CP((src).fld,(dst).fld,tv_sec); \
+ CP((src).fld,(dst).fld,tv_nsec); \
+} while (0);
+
+struct rusage32 {
+ struct timeval32 ru_utime;
+ struct timeval32 ru_stime;
+ int32_t ru_maxrss;
+ int32_t ru_ixrss;
+ int32_t ru_idrss;
+ int32_t ru_isrss;
+ int32_t ru_minflt;
+ int32_t ru_majflt;
+ int32_t ru_nswap;
+ int32_t ru_inblock;
+ int32_t ru_oublock;
+ int32_t ru_msgsnd;
+ int32_t ru_msgrcv;
+ int32_t ru_nsignals;
+ int32_t ru_nvcsw;
+ int32_t ru_nivcsw;
+};
+
+struct statfs32 {
+ int32_t f_spare2;
+ int32_t f_bsize;
+ int32_t f_iosize;
+ int32_t f_blocks;
+ int32_t f_bfree;
+ int32_t f_bavail;
+ int32_t f_files;
+ int32_t f_ffree;
+ fsid_t f_fsid;
+ uid_t f_owner;
+ int32_t f_type;
+ int32_t f_flags;
+ int32_t f_syncwrites;
+ int32_t f_asyncwrites;
+ char f_fstypename[MFSNAMELEN];
+ char f_mntonname[MNAMELEN];
+ int32_t f_syncreads;
+ int32_t f_asyncreads;
+ int16_t f_spares1;
+ char f_mntfromname[MNAMELEN];
+ int16_t f_spares2;
+ int32_t f_spare[2];
+};
+
+#endif /* !_IA64_IA32_IA32_H_ */
diff --git a/sys/amd64/ia32/ia32_misc.c b/sys/amd64/ia32/ia32_misc.c
new file mode 100644
index 000000000000..8b28bcee0a52
--- /dev/null
+++ b/sys/amd64/ia32/ia32_misc.c
@@ -0,0 +1,1339 @@
+/*-
+ * Copyright (c) 2002 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/dkstat.h>
+#include <sys/exec.h>
+#include <sys/fcntl.h>
+#include <sys/filedesc.h>
+#include <sys/imgact.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/file.h> /* Must come after sys/malloc.h */
+#include <sys/mman.h>
+#include <sys/module.h>
+#include <sys/mount.h>
+#include <sys/mutex.h>
+#include <sys/namei.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/reboot.h>
+#include <sys/resource.h>
+#include <sys/resourcevar.h>
+#include <sys/selinfo.h>
+#include <sys/pipe.h> /* Must come after sys/selinfo.h */
+#include <sys/signal.h>
+#include <sys/signalvar.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/sysent.h>
+#include <sys/sysproto.h>
+#include <sys/systm.h>
+#include <sys/unistd.h>
+#include <sys/user.h>
+#include <sys/utsname.h>
+#include <sys/vnode.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_extern.h>
+
+#include <ia64/ia32/ia32_util.h>
+#include <ia64/ia32/ia32.h>
+#include <ia64/ia32/ia32_proto.h>
+
+static const char ia32_emul_path[] = "/compat/ia32";
+/*
+ * [ taken from the linux emulator ]
+ * Search an alternate path before passing pathname arguments on
+ * to system calls. Useful for keeping a separate 'emulation tree'.
+ *
+ * If cflag is set, we check if an attempt can be made to create
+ * the named file, i.e. we check if the directory it should
+ * be in exists.
+ */
+int
+ia32_emul_find(td, sgp, prefix, path, pbuf, cflag)
+ struct thread *td;
+ caddr_t *sgp; /* Pointer to stackgap memory */
+ const char *prefix;
+ char *path;
+ char **pbuf;
+ int cflag;
+{
+ int error;
+ size_t len, sz;
+ char *buf, *cp, *ptr;
+ struct ucred *ucred;
+ struct nameidata nd;
+ struct nameidata ndroot;
+ struct vattr vat;
+ struct vattr vatroot;
+
+ buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
+ *pbuf = path;
+
+ for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++)
+ continue;
+
+ sz = MAXPATHLEN - (ptr - buf);
+
+ /*
+ * If sgp is not given then the path is already in kernel space
+ */
+ if (sgp == NULL)
+ error = copystr(path, ptr, sz, &len);
+ else
+ error = copyinstr(path, ptr, sz, &len);
+
+ if (error) {
+ free(buf, M_TEMP);
+ return error;
+ }
+
+ if (*ptr != '/') {
+ free(buf, M_TEMP);
+ return EINVAL;
+ }
+
+ /*
+ * We know that there is a / somewhere in this pathname.
+ * Search backwards for it, to find the file's parent dir
+ * to see if it exists in the alternate tree. If it does,
+ * and we want to create a file (cflag is set). We don't
+ * need to worry about the root comparison in this case.
+ */
+
+ if (cflag) {
+ for (cp = &ptr[len] - 1; *cp != '/'; cp--)
+ ;
+ *cp = '\0';
+
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
+
+ if ((error = namei(&nd)) != 0) {
+ free(buf, M_TEMP);
+ return error;
+ }
+
+ *cp = '/';
+ } else {
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
+
+ if ((error = namei(&nd)) != 0) {
+ free(buf, M_TEMP);
+ return error;
+ }
+
+ /*
+ * We now compare the vnode of the ia32_root to the one
+ * vnode asked. If they resolve to be the same, then we
+ * ignore the match so that the real root gets used.
+ * This avoids the problem of traversing "../.." to find the
+ * root directory and never finding it, because "/" resolves
+ * to the emulation root directory. This is expensive :-(
+ */
+ NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, ia32_emul_path,
+ td);
+
+ if ((error = namei(&ndroot)) != 0) {
+ /* Cannot happen! */
+ free(buf, M_TEMP);
+ vrele(nd.ni_vp);
+ return error;
+ }
+
+ ucred = td->td_ucred;
+ if ((error = VOP_GETATTR(nd.ni_vp, &vat, ucred, td)) != 0) {
+ goto bad;
+ }
+
+ if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, ucred,
+ td)) != 0) {
+ goto bad;
+ }
+
+ if (vat.va_fsid == vatroot.va_fsid &&
+ vat.va_fileid == vatroot.va_fileid) {
+ error = ENOENT;
+ goto bad;
+ }
+
+ }
+ if (sgp == NULL)
+ *pbuf = buf;
+ else {
+ sz = &ptr[len] - buf;
+ *pbuf = stackgap_alloc(sgp, sz + 1);
+ error = copyout(buf, *pbuf, sz);
+ free(buf, M_TEMP);
+ }
+
+ vrele(nd.ni_vp);
+ if (!cflag)
+ vrele(ndroot.ni_vp);
+
+ return error;
+
+bad:
+ vrele(ndroot.ni_vp);
+ vrele(nd.ni_vp);
+ free(buf, M_TEMP);
+ return error;
+}
+
+int
+ia32_open(struct thread *td, struct ia32_open_args *uap)
+{
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, uap->path);
+
+ return open(td, (struct open_args *) uap);
+}
+
+int
+ia32_wait4(struct thread *td, struct ia32_wait4_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct rusage32 *rusage32, ru32;
+ struct rusage *rusage = NULL, ru;
+
+ rusage32 = SCARG(uap, rusage);
+ if (rusage32) {
+ sg = stackgap_init();
+ rusage = stackgap_alloc(&sg, sizeof(struct rusage));
+ SCARG(uap, rusage) = (struct rusage32 *)rusage;
+ }
+ error = wait4(td, (struct wait_args *)uap);
+ if (error)
+ return (error);
+ if (rusage32 && (error = copyin(rusage, &ru, sizeof(ru)) == 0)) {
+ TV_CP(ru, ru32, ru_utime);
+ TV_CP(ru, ru32, ru_stime);
+ CP(ru, ru32, ru_maxrss);
+ CP(ru, ru32, ru_ixrss);
+ CP(ru, ru32, ru_idrss);
+ CP(ru, ru32, ru_isrss);
+ CP(ru, ru32, ru_minflt);
+ CP(ru, ru32, ru_majflt);
+ CP(ru, ru32, ru_nswap);
+ CP(ru, ru32, ru_inblock);
+ CP(ru, ru32, ru_oublock);
+ CP(ru, ru32, ru_msgsnd);
+ CP(ru, ru32, ru_msgrcv);
+ CP(ru, ru32, ru_nsignals);
+ CP(ru, ru32, ru_nvcsw);
+ CP(ru, ru32, ru_nivcsw);
+ error = copyout(&ru32, rusage32, sizeof(ru32));
+ }
+ return (error);
+}
+
+static void
+copy_statfs(struct statfs *in, struct statfs32 *out)
+{
+ CP(*in, *out, f_bsize);
+ CP(*in, *out, f_iosize);
+ CP(*in, *out, f_blocks);
+ CP(*in, *out, f_bfree);
+ CP(*in, *out, f_bavail);
+ CP(*in, *out, f_files);
+ CP(*in, *out, f_ffree);
+ CP(*in, *out, f_fsid);
+ CP(*in, *out, f_owner);
+ CP(*in, *out, f_type);
+ CP(*in, *out, f_flags);
+ CP(*in, *out, f_flags);
+ CP(*in, *out, f_syncwrites);
+ CP(*in, *out, f_asyncwrites);
+ bcopy(in->f_fstypename,
+ out->f_fstypename, MFSNAMELEN);
+ bcopy(in->f_mntonname,
+ out->f_mntonname, MNAMELEN);
+ CP(*in, *out, f_syncreads);
+ CP(*in, *out, f_asyncreads);
+ bcopy(in->f_mntfromname,
+ out->f_mntfromname, MNAMELEN);
+}
+
+int
+ia32_getfsstat(struct thread *td, struct ia32_getfsstat_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct statfs32 *sp32, stat32;
+ struct statfs *sp = NULL, stat;
+ int maxcount, count, i;
+
+ sp32 = SCARG(uap, buf);
+ maxcount = SCARG(uap, bufsize) / sizeof(struct statfs32);
+
+ if (sp32) {
+ sg = stackgap_init();
+ sp = stackgap_alloc(&sg, sizeof(struct statfs) * maxcount);
+ SCARG(uap, buf) = (struct statfs32 *)sp;
+ }
+ error = getfsstat(td, (struct getfsstat_args *) uap);
+ if (sp32 && !error) {
+ count = td->td_retval[0];
+ for (i = 0; i < count; i++) {
+ error = copyin(&sp[i], &stat, sizeof(stat));
+ if (error)
+ return (error);
+ copy_statfs(&stat, &stat32);
+ error = copyout(&stat32, &sp32[i], sizeof(stat32));
+ if (error)
+ return (error);
+ }
+ }
+ return (error);
+}
+
+int
+ia32_access(struct thread *td, struct ia32_access_args *uap)
+{
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, uap->path);
+
+ return access(td, (struct access_args *)uap);
+}
+
+int
+ia32_chflags(struct thread *td, struct ia32_chflags_args *uap)
+{
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, uap->path);
+
+ return chflags(td, (struct chflags_args *)uap);
+}
+
+struct sigaltstack32 {
+ u_int32_t ss_sp;
+ u_int32_t ss_size;
+ int ss_flags;
+};
+
+int
+ia32_sigaltstack(struct thread *td, struct ia32_sigaltstack_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct sigaltstack32 *p32, *op32, s32;
+ struct sigaltstack *p = NULL, *op = NULL, s;
+
+ p32 = SCARG(uap, ss);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct sigaltstack));
+ SCARG(uap, ss) = (struct sigaltstack32 *)p;
+ error = copyin(p32, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ PTRIN_CP(s32, s, ss_sp);
+ CP(s32, s, ss_size);
+ CP(s32, s, ss_flags);
+ error = copyout(&s, p, sizeof(s));
+ if (error)
+ return (error);
+ }
+ op32 = SCARG(uap, oss);
+ if (op32) {
+ sg = stackgap_init();
+ op = stackgap_alloc(&sg, sizeof(struct sigaltstack));
+ SCARG(uap, oss) = (struct sigaltstack32 *)op;
+ }
+ error = sigaltstack(td, (struct sigaltstack_args *) uap);
+ if (error)
+ return (error);
+ if (op32) {
+ error = copyin(op, &s, sizeof(s));
+ if (error)
+ return (error);
+ PTROUT_CP(s, s32, ss_sp);
+ CP(s, s32, ss_size);
+ CP(s, s32, ss_flags);
+ error = copyout(&s32, op32, sizeof(s32));
+ }
+ return (error);
+}
+
+int
+ia32_execve(struct thread *td, struct ia32_execve_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct execve_args ap;
+ u_int32_t *p32, arg;
+ char **p;
+ int count;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, SCARG(uap, fname));
+ SCARG(&ap, fname) = SCARG(uap, fname);
+
+ if (SCARG(uap, argv)) {
+ count = 0;
+ p32 = SCARG(uap, argv);
+ do {
+ error = copyin(p32++, &arg, sizeof(arg));
+ if (error)
+ return error;
+ count++;
+ } while (arg != 0);
+ p = stackgap_alloc(&sg, count * sizeof(char *));
+ SCARG(&ap, argv) = p;
+ p32 = SCARG(uap, argv);
+ do {
+ error = copyin(p32++, &arg, sizeof(arg));
+ if (error)
+ return error;
+ *p++ = PTRIN(arg);
+ } while (arg != 0);
+ }
+ if (SCARG(uap, envv)) {
+ count = 0;
+ p32 = SCARG(uap, envv);
+ do {
+ error = copyin(p32++, &arg, sizeof(arg));
+ if (error)
+ return error;
+ count++;
+ } while (arg != 0);
+ p = stackgap_alloc(&sg, count * sizeof(char *));
+ SCARG(&ap, envv) = p;
+ p32 = SCARG(uap, envv);
+ do {
+ error = copyin(p32++, &arg, sizeof(arg));
+ if (error)
+ return error;
+ *p++ = PTRIN(arg);
+ } while (arg != 0);
+ }
+
+ return execve(td, &ap);
+}
+
+static int
+ia32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
+ int prot, int fd, off_t pos)
+{
+ vm_map_t map;
+ vm_map_entry_t entry;
+ int rv;
+
+ map = &td->td_proc->p_vmspace->vm_map;
+ if (fd != -1)
+ prot |= VM_PROT_WRITE;
+
+ if (vm_map_lookup_entry(map, start, &entry)) {
+ if ((entry->protection & prot) != prot) {
+ rv = vm_map_protect(map,
+ trunc_page(start),
+ round_page(end),
+ entry->protection | prot,
+ FALSE);
+ if (rv != KERN_SUCCESS)
+ return (EINVAL);
+ }
+ } else {
+ vm_offset_t addr = trunc_page(start);
+ rv = vm_map_find(map, 0, 0,
+ &addr, PAGE_SIZE, FALSE, prot,
+ VM_PROT_ALL, 0);
+ if (rv != KERN_SUCCESS)
+ return (EINVAL);
+ }
+
+ if (fd != -1) {
+ struct pread_args r;
+ SCARG(&r, fd) = fd;
+ SCARG(&r, buf) = (void *) start;
+ SCARG(&r, nbyte) = end - start;
+ SCARG(&r, offset) = pos;
+ return (pread(td, &r));
+ } else {
+ while (start < end) {
+ subyte((void *) start, 0);
+ start++;
+ }
+ return (0);
+ }
+}
+
+int
+ia32_mmap(struct thread *td, struct ia32_mmap_args *uap)
+{
+ struct mmap_args ap;
+ vm_offset_t addr = (vm_offset_t) SCARG(uap, addr);
+ vm_size_t len = SCARG(uap, len);
+ int prot = SCARG(uap, prot);
+ int flags = SCARG(uap, flags);
+ int fd = SCARG(uap, fd);
+ off_t pos = (SCARG(uap, poslo)
+ | ((off_t)SCARG(uap, poshi) << 32));
+ vm_size_t pageoff;
+ int error;
+
+ /*
+ * Attempt to handle page size hassles.
+ */
+ pageoff = (pos & PAGE_MASK);
+ if (flags & MAP_FIXED) {
+ vm_offset_t start, end;
+ start = addr;
+ end = addr + len;
+
+ if (start != trunc_page(start)) {
+ error = ia32_mmap_partial(td, start, round_page(start),
+ prot, fd, pos);
+ if (fd != -1)
+ pos += round_page(start) - start;
+ start = round_page(start);
+ }
+ if (end != round_page(end)) {
+ vm_offset_t t = trunc_page(end);
+ error = ia32_mmap_partial(td, t, end,
+ prot, fd,
+ pos + t - start);
+ end = trunc_page(end);
+ }
+ if (end > start && fd != -1 && (pos & PAGE_MASK)) {
+ /*
+ * We can't map this region at all. The specified
+ * address doesn't have the same alignment as the file
+ * position. Fake the mapping by simply reading the
+ * entire region into memory. First we need to make
+ * sure the region exists.
+ */
+ vm_map_t map;
+ struct pread_args r;
+ int rv;
+
+ prot |= VM_PROT_WRITE;
+ map = &td->td_proc->p_vmspace->vm_map;
+ rv = vm_map_remove(map, start, end);
+ if (rv != KERN_SUCCESS)
+ return (EINVAL);
+ rv = vm_map_find(map, 0, 0,
+ &start, end - start, FALSE,
+ prot, VM_PROT_ALL, 0);
+ if (rv != KERN_SUCCESS)
+ return (EINVAL);
+ SCARG(&r, fd) = fd;
+ SCARG(&r, buf) = (void *) start;
+ SCARG(&r, nbyte) = end - start;
+ SCARG(&r, offset) = pos;
+ error = pread(td, &r);
+ if (error)
+ return (error);
+
+ td->td_retval[0] = addr;
+ return (0);
+ }
+ if (end == start) {
+ /*
+ * After dealing with the ragged ends, there
+ * might be none left.
+ */
+ td->td_retval[0] = addr;
+ return (0);
+ }
+ addr = start;
+ len = end - start;
+ }
+
+ SCARG(&ap, addr) = (void *) addr;
+ SCARG(&ap, len) = len;
+ SCARG(&ap, prot) = prot;
+ SCARG(&ap, flags) = flags;
+ SCARG(&ap, fd) = fd;
+ SCARG(&ap, pos) = pos;
+
+ return (mmap(td, &ap));
+}
+
+struct itimerval32 {
+ struct timeval32 it_interval;
+ struct timeval32 it_value;
+};
+
+int
+ia32_setitimer(struct thread *td, struct ia32_setitimer_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct itimerval32 *p32, *op32, s32;
+ struct itimerval *p = NULL, *op = NULL, s;
+
+ p32 = SCARG(uap, itv);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct itimerval));
+ SCARG(uap, itv) = (struct itimerval32 *)p;
+ error = copyin(p32, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ TV_CP(s32, s, it_interval);
+ TV_CP(s32, s, it_value);
+ error = copyout(&s, p, sizeof(s));
+ if (error)
+ return (error);
+ }
+ op32 = SCARG(uap, oitv);
+ if (op32) {
+ sg = stackgap_init();
+ op = stackgap_alloc(&sg, sizeof(struct itimerval));
+ SCARG(uap, oitv) = (struct itimerval32 *)op;
+ }
+ error = setitimer(td, (struct setitimer_args *) uap);
+ if (error)
+ return (error);
+ if (op32) {
+ error = copyin(op, &s, sizeof(s));
+ if (error)
+ return (error);
+ TV_CP(s, s32, it_interval);
+ TV_CP(s, s32, it_value);
+ error = copyout(&s32, op32, sizeof(s32));
+ }
+ return (error);
+}
+
+int
+ia32_select(struct thread *td, struct ia32_select_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct timeval32 *p32, s32;
+ struct timeval *p = NULL, s;
+
+ p32 = SCARG(uap, tv);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct timeval));
+ SCARG(uap, tv) = (struct timeval32 *)p;
+ error = copyin(p32, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ CP(s32, s, tv_sec);
+ CP(s32, s, tv_usec);
+ error = copyout(&s, p, sizeof(s));
+ if (error)
+ return (error);
+ }
+ /*
+ * XXX big-endian needs to convert the fd_sets too.
+ */
+ return (select(td, (struct select_args *) uap));
+}
+
+int
+ia32_gettimeofday(struct thread *td, struct ia32_gettimeofday_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct timeval32 *p32, s32;
+ struct timeval *p = NULL, s;
+
+ p32 = SCARG(uap, tp);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct timeval));
+ SCARG(uap, tp) = (struct timeval32 *)p;
+ }
+ error = gettimeofday(td, (struct gettimeofday_args *) uap);
+ if (error)
+ return (error);
+ if (p32) {
+ error = copyin(p, &s, sizeof(s));
+ if (error)
+ return (error);
+ CP(s, s32, tv_sec);
+ CP(s, s32, tv_usec);
+ error = copyout(&s32, p32, sizeof(s32));
+ if (error)
+ return (error);
+ }
+ return (error);
+}
+
+int
+ia32_getrusage(struct thread *td, struct ia32_getrusage_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct rusage32 *p32, s32;
+ struct rusage *p = NULL, s;
+
+ p32 = SCARG(uap, rusage);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct rusage));
+ SCARG(uap, rusage) = (struct rusage32 *)p;
+ }
+ error = getrusage(td, (struct getrusage_args *) uap);
+ if (error)
+ return (error);
+ if (p32) {
+ error = copyin(p, &s, sizeof(s));
+ if (error)
+ return (error);
+ TV_CP(s, s32, ru_utime);
+ TV_CP(s, s32, ru_stime);
+ CP(s, s32, ru_maxrss);
+ CP(s, s32, ru_ixrss);
+ CP(s, s32, ru_idrss);
+ CP(s, s32, ru_isrss);
+ CP(s, s32, ru_minflt);
+ CP(s, s32, ru_majflt);
+ CP(s, s32, ru_nswap);
+ CP(s, s32, ru_inblock);
+ CP(s, s32, ru_oublock);
+ CP(s, s32, ru_msgsnd);
+ CP(s, s32, ru_msgrcv);
+ CP(s, s32, ru_nsignals);
+ CP(s, s32, ru_nvcsw);
+ CP(s, s32, ru_nivcsw);
+ error = copyout(&s32, p32, sizeof(s32));
+ }
+ return (error);
+}
+
+struct iovec32 {
+ u_int32_t iov_base;
+ int iov_len;
+};
+#define STACKGAPLEN 400
+
+int
+ia32_readv(struct thread *td, struct ia32_readv_args *uap)
+{
+ int error, osize, nsize, i;
+ caddr_t sg;
+ struct readv_args /* {
+ syscallarg(int) fd;
+ syscallarg(struct iovec *) iovp;
+ syscallarg(u_int) iovcnt;
+ } */ a;
+ struct iovec32 *oio;
+ struct iovec *nio;
+
+ sg = stackgap_init();
+
+ if (SCARG(uap, iovcnt) > (STACKGAPLEN / sizeof (struct iovec)))
+ return (EINVAL);
+
+ osize = SCARG(uap, iovcnt) * sizeof (struct iovec32);
+ nsize = SCARG(uap, iovcnt) * sizeof (struct iovec);
+
+ oio = malloc(osize, M_TEMP, M_WAITOK);
+ nio = malloc(nsize, M_TEMP, M_WAITOK);
+
+ error = 0;
+ if ((error = copyin(SCARG(uap, iovp), oio, osize)))
+ goto punt;
+ for (i = 0; i < SCARG(uap, iovcnt); i++) {
+ nio[i].iov_base = PTRIN(oio[i].iov_base);
+ nio[i].iov_len = oio[i].iov_len;
+ }
+
+ SCARG(&a, fd) = SCARG(uap, fd);
+ SCARG(&a, iovp) = stackgap_alloc(&sg, nsize);
+ SCARG(&a, iovcnt) = SCARG(uap, iovcnt);
+
+ if ((error = copyout(nio, (caddr_t)SCARG(&a, iovp), nsize)))
+ goto punt;
+ error = readv(td, &a);
+
+punt:
+ free(oio, M_TEMP);
+ free(nio, M_TEMP);
+ return (error);
+}
+
+int
+ia32_writev(struct thread *td, struct ia32_writev_args *uap)
+{
+ int error, i, nsize, osize;
+ caddr_t sg;
+ struct writev_args /* {
+ syscallarg(int) fd;
+ syscallarg(struct iovec *) iovp;
+ syscallarg(u_int) iovcnt;
+ } */ a;
+ struct iovec32 *oio;
+ struct iovec *nio;
+
+ sg = stackgap_init();
+
+ if (SCARG(uap, iovcnt) > (STACKGAPLEN / sizeof (struct iovec)))
+ return (EINVAL);
+
+ osize = SCARG(uap, iovcnt) * sizeof (struct iovec32);
+ nsize = SCARG(uap, iovcnt) * sizeof (struct iovec);
+
+ oio = malloc(osize, M_TEMP, M_WAITOK);
+ nio = malloc(nsize, M_TEMP, M_WAITOK);
+
+ error = 0;
+ if ((error = copyin(SCARG(uap, iovp), oio, osize)))
+ goto punt;
+ for (i = 0; i < SCARG(uap, iovcnt); i++) {
+ nio[i].iov_base = PTRIN(oio[i].iov_base);
+ nio[i].iov_len = oio[i].iov_len;
+ }
+
+ SCARG(&a, fd) = SCARG(uap, fd);
+ SCARG(&a, iovp) = stackgap_alloc(&sg, nsize);
+ SCARG(&a, iovcnt) = SCARG(uap, iovcnt);
+
+ if ((error = copyout(nio, (caddr_t)SCARG(&a, iovp), nsize)))
+ goto punt;
+ error = writev(td, &a);
+
+punt:
+ free(oio, M_TEMP);
+ free(nio, M_TEMP);
+ return (error);
+}
+
+int
+ia32_settimeofday(struct thread *td, struct ia32_settimeofday_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct timeval32 *p32, s32;
+ struct timeval *p = NULL, s;
+
+ p32 = SCARG(uap, tv);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct timeval));
+ SCARG(uap, tv) = (struct timeval32 *)p;
+ error = copyin(p32, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ CP(s32, s, tv_sec);
+ CP(s32, s, tv_usec);
+ error = copyout(&s, p, sizeof(s));
+ if (error)
+ return (error);
+ }
+ return (settimeofday(td, (struct settimeofday_args *) uap));
+}
+
+int
+ia32_utimes(struct thread *td, struct ia32_utimes_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct timeval32 *p32, s32[2];
+ struct timeval *p = NULL, s[2];
+
+ p32 = SCARG(uap, tptr);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, 2*sizeof(struct timeval));
+ SCARG(uap, tptr) = (struct timeval32 *)p;
+ error = copyin(p32, s32, sizeof(s32));
+ if (error)
+ return (error);
+ CP(s32[0], s[0], tv_sec);
+ CP(s32[0], s[0], tv_usec);
+ CP(s32[1], s[1], tv_sec);
+ CP(s32[1], s[1], tv_usec);
+ error = copyout(s, p, sizeof(s));
+ if (error)
+ return (error);
+ }
+ return (utimes(td, (struct utimes_args *) uap));
+}
+
+int
+ia32_adjtime(struct thread *td, struct ia32_adjtime_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct timeval32 *p32, *op32, s32;
+ struct timeval *p = NULL, *op = NULL, s;
+
+ p32 = SCARG(uap, delta);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct timeval));
+ SCARG(uap, delta) = (struct timeval32 *)p;
+ error = copyin(p32, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ CP(s32, s, tv_sec);
+ CP(s32, s, tv_usec);
+ error = copyout(&s, p, sizeof(s));
+ if (error)
+ return (error);
+ }
+ op32 = SCARG(uap, olddelta);
+ if (op32) {
+ sg = stackgap_init();
+ op = stackgap_alloc(&sg, sizeof(struct timeval));
+ SCARG(uap, olddelta) = (struct timeval32 *)op;
+ }
+ error = utimes(td, (struct utimes_args *) uap);
+ if (error)
+ return error;
+ if (op32) {
+ error = copyin(op, &s, sizeof(s));
+ if (error)
+ return (error);
+ CP(s, s32, tv_sec);
+ CP(s, s32, tv_usec);
+ error = copyout(&s32, op32, sizeof(s32));
+ }
+ return (error);
+}
+
+int
+ia32_statfs(struct thread *td, struct ia32_statfs_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct statfs32 *p32, s32;
+ struct statfs *p = NULL, s;
+
+ p32 = SCARG(uap, buf);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct statfs));
+ SCARG(uap, buf) = (struct statfs32 *)p;
+ }
+ error = statfs(td, (struct statfs_args *) uap);
+ if (error)
+ return (error);
+ if (p32) {
+ error = copyin(p, &s, sizeof(s));
+ if (error)
+ return (error);
+ copy_statfs(&s, &s32);
+ error = copyout(&s32, p32, sizeof(s32));
+ }
+ return (error);
+}
+
+int
+ia32_fstatfs(struct thread *td, struct ia32_fstatfs_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct statfs32 *p32, s32;
+ struct statfs *p = NULL, s;
+
+ p32 = SCARG(uap, buf);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct statfs));
+ SCARG(uap, buf) = (struct statfs32 *)p;
+ }
+ error = fstatfs(td, (struct fstatfs_args *) uap);
+ if (error)
+ return (error);
+ if (p32) {
+ error = copyin(p, &s, sizeof(s));
+ if (error)
+ return (error);
+ copy_statfs(&s, &s32);
+ error = copyout(&s32, p32, sizeof(s32));
+ }
+ return (error);
+}
+
+int
+ia32_semsys(struct thread *td, struct ia32_semsys_args *uap)
+{
+ /*
+ * Vector through to semsys if it is loaded.
+ */
+ return sysent[169].sy_call(td, uap);
+}
+
+int
+ia32_msgsys(struct thread *td, struct ia32_msgsys_args *uap)
+{
+ /*
+ * Vector through to msgsys if it is loaded.
+ */
+ return sysent[170].sy_call(td, uap);
+}
+
+int
+ia32_shmsys(struct thread *td, struct ia32_shmsys_args *uap)
+{
+ /*
+ * Vector through to shmsys if it is loaded.
+ */
+ return sysent[171].sy_call(td, uap);
+}
+
+int
+ia32_pread(struct thread *td, struct ia32_pread_args *uap)
+{
+ struct pread_args ap;
+
+ SCARG(&ap, fd) = SCARG(uap, fd);
+ SCARG(&ap, buf) = SCARG(uap, buf);
+ SCARG(&ap, nbyte) = SCARG(uap, nbyte);
+ SCARG(&ap, offset) = (SCARG(uap, offsetlo)
+ | ((off_t)SCARG(uap, offsethi) << 32));
+ return (pread(td, &ap));
+}
+
+int
+ia32_pwrite(struct thread *td, struct ia32_pwrite_args *uap)
+{
+ struct pwrite_args ap;
+
+ SCARG(&ap, fd) = SCARG(uap, fd);
+ SCARG(&ap, buf) = SCARG(uap, buf);
+ SCARG(&ap, nbyte) = SCARG(uap, nbyte);
+ SCARG(&ap, offset) = (SCARG(uap, offsetlo)
+ | ((off_t)SCARG(uap, offsethi) << 32));
+ return (pwrite(td, &ap));
+}
+
+int
+ia32_lseek(struct thread *td, struct ia32_lseek_args *uap)
+{
+ int error;
+ struct lseek_args ap;
+ off_t pos;
+
+ SCARG(&ap, fd) = SCARG(uap, fd);
+ SCARG(&ap, offset) = (SCARG(uap, offsetlo)
+ | ((off_t)SCARG(uap, offsethi) << 32));
+ SCARG(&ap, whence) = SCARG(uap, whence);
+ error = lseek(td, &ap);
+ /* Expand the quad return into two parts for eax and edx */
+ pos = *(off_t *)(td->td_retval);
+ td->td_retval[0] = pos & 0xffffffff; /* %eax */
+ td->td_retval[1] = pos >> 32; /* %edx */
+ return error;
+}
+
+int
+ia32_truncate(struct thread *td, struct ia32_truncate_args *uap)
+{
+ struct truncate_args ap;
+
+ SCARG(&ap, path) = SCARG(uap, path);
+ SCARG(&ap, length) = (SCARG(uap, lengthlo)
+ | ((off_t)SCARG(uap, lengthhi) << 32));
+ return (truncate(td, &ap));
+}
+
+int
+ia32_ftruncate(struct thread *td, struct ia32_ftruncate_args *uap)
+{
+ struct ftruncate_args ap;
+
+ SCARG(&ap, fd) = SCARG(uap, fd);
+ SCARG(&ap, length) = (SCARG(uap, lengthlo)
+ | ((off_t)SCARG(uap, lengthhi) << 32));
+ return (ftruncate(td, &ap));
+}
+
+int
+ia32_sendfile(struct thread *td, struct ia32_sendfile_args *uap)
+{
+ struct sendfile_args ap;
+
+ SCARG(&ap, fd) = SCARG(uap, fd);
+ SCARG(&ap, s) = SCARG(uap, s);
+ SCARG(&ap, offset) = (SCARG(uap, offsetlo)
+ | ((off_t)SCARG(uap, offsethi) << 32));
+ SCARG(&ap, nbytes) = SCARG(uap, nbytes); /* XXX check */
+ SCARG(&ap, hdtr) = SCARG(uap, hdtr); /* XXX check */
+ SCARG(&ap, sbytes) = SCARG(uap, sbytes); /* XXX FIXME!! */
+ SCARG(&ap, flags) = SCARG(uap, flags);
+ return (sendfile(td, &ap));
+}
+
+struct stat32 {
+ udev_t st_dev;
+ ino_t st_ino;
+ mode_t st_mode;
+ nlink_t st_nlink;
+ uid_t st_uid;
+ gid_t st_gid;
+ udev_t st_rdev;
+ struct timespec32 st_atimespec;
+ struct timespec32 st_mtimespec;
+ struct timespec32 st_ctimespec;
+ off_t st_size;
+ int64_t st_blocks;
+ u_int32_t st_blksize;
+ u_int32_t st_flags;
+ u_int32_t st_gen;
+};
+
+static void
+copy_stat( struct stat *in, struct stat32 *out)
+{
+ CP(*in, *out, st_dev);
+ CP(*in, *out, st_ino);
+ CP(*in, *out, st_mode);
+ CP(*in, *out, st_nlink);
+ CP(*in, *out, st_uid);
+ CP(*in, *out, st_gid);
+ CP(*in, *out, st_rdev);
+ TS_CP(*in, *out, st_atimespec);
+ TS_CP(*in, *out, st_mtimespec);
+ TS_CP(*in, *out, st_ctimespec);
+ CP(*in, *out, st_size);
+ CP(*in, *out, st_blocks);
+ CP(*in, *out, st_blksize);
+ CP(*in, *out, st_flags);
+ CP(*in, *out, st_gen);
+}
+
+int
+ia32_stat(struct thread *td, struct ia32_stat_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct stat32 *p32, s32;
+ struct stat *p = NULL, s;
+
+ p32 = SCARG(uap, ub);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct stat));
+ SCARG(uap, ub) = (struct stat32 *)p;
+ }
+ error = stat(td, (struct stat_args *) uap);
+ if (error)
+ return (error);
+ if (p32) {
+ error = copyin(p, &s, sizeof(s));
+ if (error)
+ return (error);
+ copy_stat(&s, &s32);
+ error = copyout(&s32, p32, sizeof(s32));
+ }
+ return (error);
+}
+
+int
+ia32_fstat(struct thread *td, struct ia32_fstat_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct stat32 *p32, s32;
+ struct stat *p = NULL, s;
+
+ p32 = SCARG(uap, ub);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct stat));
+ SCARG(uap, ub) = (struct stat32 *)p;
+ }
+ error = fstat(td, (struct fstat_args *) uap);
+ if (error)
+ return (error);
+ if (p32) {
+ error = copyin(p, &s, sizeof(s));
+ if (error)
+ return (error);
+ copy_stat(&s, &s32);
+ error = copyout(&s32, p32, sizeof(s32));
+ }
+ return (error);
+}
+
+int
+ia32_lstat(struct thread *td, struct ia32_lstat_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct stat32 *p32, s32;
+ struct stat *p = NULL, s;
+
+ p32 = SCARG(uap, ub);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct stat));
+ SCARG(uap, ub) = (struct stat32 *)p;
+ }
+ error = lstat(td, (struct lstat_args *) uap);
+ if (error)
+ return (error);
+ if (p32) {
+ error = copyin(p, &s, sizeof(s));
+ if (error)
+ return (error);
+ copy_stat(&s, &s32);
+ error = copyout(&s32, p32, sizeof(s32));
+ }
+ return (error);
+}
+
+/*
+ * MPSAFE
+ */
+int
+ia32_sysctl(struct thread *td, struct ia32_sysctl_args *uap)
+{
+ int error, name[CTL_MAXNAME];
+ size_t j, oldlen;
+
+ if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
+ return (EINVAL);
+
+ error = copyin(uap->name, &name, uap->namelen * sizeof(int));
+ if (error)
+ return (error);
+
+ mtx_lock(&Giant);
+
+ if (uap->oldlenp)
+ oldlen = fuword32(uap->oldlenp);
+ else
+ oldlen = 0;
+ error = userland_sysctl(td, name, uap->namelen,
+ uap->old, &oldlen, 1,
+ uap->new, uap->newlen, &j);
+ if (error && error != ENOMEM)
+ goto done2;
+ if (uap->oldlenp) {
+ suword32(uap->oldlenp, j);
+ }
+done2:
+ mtx_unlock(&Giant);
+ return (error);
+}
+
+struct sigaction32 {
+ u_int32_t sa_u;
+ int sa_flags;
+ sigset_t sa_mask;
+};
+
+int
+ia32_sigaction(struct thread *td, struct ia32_sigaction_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct sigaction32 *p32, *op32, s32;
+ struct sigaction *p = NULL, *op = NULL, s;
+
+ p32 = SCARG(uap, act);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct sigaction));
+ SCARG(uap, act) = (struct sigaction32 *)p;
+ error = copyin(p32, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ s.sa_handler = PTRIN(s32.sa_u);
+ CP(s32, s, sa_flags);
+ CP(s32, s, sa_mask);
+ error = copyout(&s, p, sizeof(s));
+ if (error)
+ return (error);
+ }
+ op32 = SCARG(uap, oact);
+ if (op32) {
+ sg = stackgap_init();
+ op = stackgap_alloc(&sg, sizeof(struct sigaction));
+ SCARG(uap, oact) = (struct sigaction32 *)op;
+ }
+ error = sigaction(td, (struct sigaction_args *) uap);
+ if (error)
+ return (error);
+ if (op32) {
+ error = copyin(op, &s, sizeof(s));
+ if (error)
+ return (error);
+ s32.sa_u = PTROUT(s.sa_handler);
+ CP(s, s32, sa_flags);
+ CP(s, s32, sa_mask);
+ error = copyout(&s32, op32, sizeof(s32));
+ }
+ return (error);
+}
+
+#if 0
+
+int
+ia32_xxx(struct thread *td, struct ia32_xxx_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct yyy32 *p32, s32;
+ struct yyy *p = NULL, s;
+
+ p32 = SCARG(uap, zzz);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct yyy));
+ SCARG(uap, zzz) = (struct yyy32 *)p;
+ error = copyin(p32, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ /* translate in */
+ error = copyout(&s, p, sizeof(s));
+ if (error)
+ return (error);
+ }
+ error = xxx(td, (struct xxx_args *) uap);
+ if (error)
+ return (error);
+ if (p32) {
+ error = copyin(p, &s, sizeof(s));
+ if (error)
+ return (error);
+ /* translate out */
+ error = copyout(&s32, p32, sizeof(s32));
+ }
+ return (error);
+}
+
+#endif
diff --git a/sys/amd64/ia32/ia32_sysvec.c b/sys/amd64/ia32/ia32_sysvec.c
new file mode 100644
index 000000000000..06e6505a4b3e
--- /dev/null
+++ b/sys/amd64/ia32/ia32_sysvec.c
@@ -0,0 +1,365 @@
+/*-
+ * Copyright (c) 2002 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#define __ELF_WORD_SIZE 32
+
+#include <sys/param.h>
+#include <sys/exec.h>
+#include <sys/fcntl.h>
+#include <sys/imgact.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/mman.h>
+#include <sys/namei.h>
+#include <sys/pioctl.h>
+#include <sys/proc.h>
+#include <sys/procfs.h>
+#include <sys/resourcevar.h>
+#include <sys/systm.h>
+#include <sys/signalvar.h>
+#include <sys/stat.h>
+#include <sys/sx.h>
+#include <sys/syscall.h>
+#include <sys/sysctl.h>
+#include <sys/sysent.h>
+#include <sys/vnode.h>
+#include <sys/imgact_elf.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_extern.h>
+
+#include <ia64/ia32/ia32_util.h>
+#include <i386/include/psl.h>
+#include <i386/include/segments.h>
+#include <i386/include/specialreg.h>
+#include <machine/frame.h>
+#include <machine/md_var.h>
+
+static register_t *ia32_copyout_strings(struct image_params *imgp);
+static void ia32_setregs(struct thread *td, u_long entry, u_long stack,
+ u_long ps_strings);
+
+extern struct sysent ia32_sysent[];
+
+static char ia32_sigcode[] = {
+ 0xff, 0x54, 0x24, 0x10, /* call *SIGF_HANDLER(%esp) */
+ 0x8d, 0x44, 0x24, 0x14, /* lea SIGF_UC(%esp),%eax */
+ 0x50, /* pushl %eax */
+ 0xf7, 0x40, 0x54, 0x00, 0x00, 0x02, 0x02, /* testl $PSL_VM,UC_EFLAGS(%eax) */
+ 0x75, 0x03, /* jne 9f */
+ 0x8e, 0x68, 0x14, /* movl UC_GS(%eax),%gs */
+ 0xb8, 0x57, 0x01, 0x00, 0x00, /* 9: movl $SYS_sigreturn,%eax */
+ 0x50, /* pushl %eax */
+ 0xcd, 0x80, /* int $0x80 */
+ 0xeb, 0xfe, /* 0: jmp 0b */
+ 0, 0, 0, 0
+};
+static int ia32_szsigcode = sizeof(ia32_sigcode) & ~3;
+
+struct sysentvec ia32_freebsd_sysvec = {
+ SYS_MAXSYSCALL,
+ ia32_sysent,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ elf32_freebsd_fixup,
+ sendsig,
+ ia32_sigcode,
+ &ia32_szsigcode,
+ 0,
+ "FreeBSD ELF",
+ elf32_coredump,
+ NULL,
+ MINSIGSTKSZ,
+ 4096,
+ IA32_USRSTACK,
+ IA32_USRSTACK,
+ ia32_copyout_strings,
+ ia32_setregs
+};
+
+static Elf32_Brandinfo ia32_brand_info = {
+ ELFOSABI_FREEBSD,
+ EM_386,
+ "FreeBSD",
+ "/compat/ia32",
+ "/usr/libexec/ld-elf.so.1",
+ &ia32_freebsd_sysvec
+ };
+
+SYSINIT(ia32, SI_SUB_EXEC, SI_ORDER_ANY,
+ (sysinit_cfunc_t) elf32_insert_brand_entry,
+ &ia32_brand_info);
+
+static register_t *
+ia32_copyout_strings(struct image_params *imgp)
+{
+ int argc, envc;
+ u_int32_t *vectp;
+ char *stringp, *destp;
+ u_int32_t *stack_base;
+ struct ia32_ps_strings *arginfo;
+ int szsigcode;
+
+ /*
+ * Calculate string base and vector table pointers.
+ * Also deal with signal trampoline code for this exec type.
+ */
+ arginfo = (struct ia32_ps_strings *)IA32_PS_STRINGS;
+ szsigcode = *(imgp->proc->p_sysent->sv_szsigcode);
+ destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE -
+ roundup((ARG_MAX - imgp->stringspace), sizeof(char *));
+
+ /*
+ * install sigcode
+ */
+ if (szsigcode)
+ copyout(imgp->proc->p_sysent->sv_sigcode,
+ ((caddr_t)arginfo - szsigcode), szsigcode);
+
+ /*
+ * If we have a valid auxargs ptr, prepare some room
+ * on the stack.
+ */
+ if (imgp->auxargs) {
+ /*
+ * 'AT_COUNT*2' is size for the ELF Auxargs data. This is for
+ * lower compatibility.
+ */
+ imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size
+ : (AT_COUNT * 2);
+ /*
+ * The '+ 2' is for the null pointers at the end of each of
+ * the arg and env vector sets,and imgp->auxarg_size is room
+ * for argument of Runtime loader.
+ */
+ vectp = (u_int32_t *) (destp - (imgp->argc + imgp->envc + 2 +
+ imgp->auxarg_size) * sizeof(u_int32_t));
+
+ } else
+ /*
+ * The '+ 2' is for the null pointers at the end of each of
+ * the arg and env vector sets
+ */
+ vectp = (u_int32_t *)
+ (destp - (imgp->argc + imgp->envc + 2) * sizeof(u_int32_t));
+
+ /*
+ * vectp also becomes our initial stack base
+ */
+ stack_base = vectp;
+
+ stringp = imgp->stringbase;
+ argc = imgp->argc;
+ envc = imgp->envc;
+
+ /*
+ * Copy out strings - arguments and environment.
+ */
+ copyout(stringp, destp, ARG_MAX - imgp->stringspace);
+
+ /*
+ * Fill in "ps_strings" struct for ps, w, etc.
+ */
+ suword32(&arginfo->ps_argvstr, (u_int32_t)(intptr_t)vectp);
+ suword32(&arginfo->ps_nargvstr, argc);
+
+ /*
+ * Fill in argument portion of vector table.
+ */
+ for (; argc > 0; --argc) {
+ suword32(vectp++, (u_int32_t)(intptr_t)destp);
+ while (*stringp++ != 0)
+ destp++;
+ destp++;
+ }
+
+ /* a null vector table pointer separates the argp's from the envp's */
+ suword32(vectp++, 0);
+
+ suword32(&arginfo->ps_envstr, (u_int32_t)(intptr_t)vectp);
+ suword32(&arginfo->ps_nenvstr, envc);
+
+ /*
+ * Fill in environment portion of vector table.
+ */
+ for (; envc > 0; --envc) {
+ suword32(vectp++, (u_int32_t)(intptr_t)destp);
+ while (*stringp++ != 0)
+ destp++;
+ destp++;
+ }
+
+ /* end of vector table is a null pointer */
+ suword32(vectp, 0);
+
+ return ((register_t *)stack_base);
+}
+
+static void
+ia32_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings)
+{
+ struct trapframe *frame = td->td_frame;
+ vm_offset_t gdt, ldt;
+ u_int64_t codesel, datasel, ldtsel;
+ u_int64_t codeseg, dataseg, gdtseg, ldtseg;
+ struct segment_descriptor desc;
+ struct vmspace *vmspace = td->td_proc->p_vmspace;
+
+ /*
+ * Make sure that we restore the entire trapframe after an
+ * execve.
+ */
+ frame->tf_flags &= ~FRAME_SYSCALL;
+
+ bzero(frame->tf_r, sizeof(frame->tf_r));
+ bzero(frame->tf_f, sizeof(frame->tf_f));
+
+ frame->tf_cr_iip = entry;
+ frame->tf_cr_ipsr = (IA64_PSR_IC
+ | IA64_PSR_I
+ | IA64_PSR_IT
+ | IA64_PSR_DT
+ | IA64_PSR_RT
+ | IA64_PSR_DFH
+ | IA64_PSR_IS
+ | IA64_PSR_BN
+ | IA64_PSR_CPL_USER);
+ frame->tf_r[FRAME_R12] = stack;
+
+ codesel = LSEL(LUCODE_SEL, SEL_UPL);
+ datasel = LSEL(LUDATA_SEL, SEL_UPL);
+ ldtsel = GSEL(GLDT_SEL, SEL_UPL);
+
+#if 1
+ frame->tf_r[FRAME_R16] = (datasel << 48) | (datasel << 32)
+ | (datasel << 16) | datasel;
+ frame->tf_r[FRAME_R17] = (ldtsel << 32) | (datasel << 16) | codesel;
+#else
+ frame->tf_r[FRAME_R16] = datasel;
+ frame->tf_r[FRAME_R17] = codesel;
+ frame->tf_r[FRAME_R18] = datasel;
+ frame->tf_r[FRAME_R19] = datasel;
+ frame->tf_r[FRAME_R20] = datasel;
+ frame->tf_r[FRAME_R21] = datasel;
+ frame->tf_r[FRAME_R22] = ldtsel;
+#endif
+
+ /*
+ * Build the GDT and LDT.
+ */
+ gdt = IA32_USRSTACK;
+ vm_map_find(&vmspace->vm_map, 0, 0,
+ &gdt, PAGE_SIZE, 0,
+ VM_PROT_ALL, VM_PROT_ALL, 0);
+ ldt = gdt + 4096;
+
+ desc.sd_lolimit = 8*NLDT-1;
+ desc.sd_lobase = ldt & 0xffffff;
+ desc.sd_type = SDT_SYSLDT;
+ desc.sd_dpl = SEL_UPL;
+ desc.sd_p = 1;
+ desc.sd_hilimit = 0;
+ desc.sd_def32 = 0;
+ desc.sd_gran = 0;
+ desc.sd_hibase = ldt >> 24;
+ copyout(&desc, (caddr_t) gdt + 8*GLDT_SEL, sizeof(desc));
+
+ desc.sd_lolimit = ((IA32_USRSTACK >> 12) - 1) & 0xffff;
+ desc.sd_lobase = 0;
+ desc.sd_type = SDT_MEMERA;
+ desc.sd_dpl = SEL_UPL;
+ desc.sd_p = 1;
+ desc.sd_hilimit = ((IA32_USRSTACK >> 12) - 1) >> 16;
+ desc.sd_def32 = 1;
+ desc.sd_gran = 1;
+ desc.sd_hibase = 0;
+ copyout(&desc, (caddr_t) ldt + 8*LUCODE_SEL, sizeof(desc));
+ desc.sd_type = SDT_MEMRWA;
+ copyout(&desc, (caddr_t) ldt + 8*LUDATA_SEL, sizeof(desc));
+
+ codeseg = 0 /* base */
+ + (((IA32_USRSTACK >> 12) - 1) << 32) /* limit */
+ + ((long)SDT_MEMERA << 52)
+ + ((long)SEL_UPL << 57)
+ + (1L << 59) /* present */
+ + (1L << 62) /* 32 bits */
+ + (1L << 63); /* page granularity */
+ dataseg = 0 /* base */
+ + (((IA32_USRSTACK >> 12) - 1) << 32) /* limit */
+ + ((long)SDT_MEMRWA << 52)
+ + ((long)SEL_UPL << 57)
+ + (1L << 59) /* present */
+ + (1L << 62) /* 32 bits */
+ + (1L << 63); /* page granularity */
+ ia64_set_csd(codeseg);
+ ia64_set_ssd(dataseg);
+ frame->tf_r[FRAME_R24] = dataseg; /* ESD */
+ frame->tf_r[FRAME_R27] = dataseg; /* DSD */
+ frame->tf_r[FRAME_R28] = dataseg; /* FSD */
+ frame->tf_r[FRAME_R29] = dataseg; /* GSD */
+
+ gdtseg = gdt /* base */
+ + ((8L*NGDT - 1) << 32) /* limit */
+ + ((long)SDT_SYSNULL << 52)
+ + ((long)SEL_UPL << 57)
+ + (1L << 59) /* present */
+ + (0L << 62) /* 16 bits */
+ + (0L << 63); /* byte granularity */
+ ldtseg = ldt /* base */
+ + ((8L*NLDT - 1) << 32) /* limit */
+ + ((long)SDT_SYSLDT << 52)
+ + ((long)SEL_UPL << 57)
+ + (1L << 59) /* present */
+ + (0L << 62) /* 16 bits */
+ + (0L << 63); /* byte granularity */
+ frame->tf_r[FRAME_R30] = ldtseg; /* LDTD */
+ frame->tf_r[FRAME_R31] = gdtseg; /* GDTD */
+
+ ia64_set_eflag(PSL_USER);
+
+ /* PS_STRINGS value for BSD/OS binaries. It is 0 for non-BSD/OS. */
+ frame->tf_r[FRAME_R11] = IA32_PS_STRINGS;
+
+ /*
+ * XXX - Linux emulator
+ * Make sure sure edx is 0x0 on entry. Linux binaries depend
+ * on it.
+ */
+ td->td_retval[1] = 0;
+}
diff --git a/sys/amd64/ia32/ia32_util.h b/sys/amd64/ia32/ia32_util.h
new file mode 100644
index 000000000000..b9e0a7c4d98a
--- /dev/null
+++ b/sys/amd64/ia32/ia32_util.h
@@ -0,0 +1,94 @@
+/*-
+ * Copyright (c) 1998-1999 Andrew Gallatin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+
+
+#include <sys/exec.h>
+#include <sys/sysent.h>
+#include <sys/cdefs.h>
+
+
+#ifndef SCARG
+#define SCARG(p, x) (p)->x
+#endif
+
+struct ia32_ps_strings {
+ u_int32_t ps_argvstr; /* first of 0 or more argument strings */
+ int ps_nargvstr; /* the number of argument strings */
+ u_int32_t ps_envstr; /* first of 0 or more environment strings */
+ int ps_nenvstr; /* the number of environment strings */
+};
+
+#define IA32_USRSTACK (4L*1024*1024*1024 - PAGE_SIZE)
+#define IA32_PS_STRINGS (IA32_USRSTACK - sizeof(struct ia32_ps_strings))
+
+static __inline caddr_t stackgap_init(void);
+static __inline void *stackgap_alloc(caddr_t *, size_t);
+
+static __inline caddr_t
+stackgap_init()
+{
+#define szsigcode (*(curproc->p_sysent->sv_szsigcode))
+ return (caddr_t)(((caddr_t)IA32_PS_STRINGS) - szsigcode - SPARE_USRSPACE);
+#undef szsigcode
+}
+
+static __inline void *
+stackgap_alloc(sgp, sz)
+ caddr_t *sgp;
+ size_t sz;
+{
+ void *p;
+
+ p = (void *) *sgp;
+ *sgp += ALIGN(sz);
+ return p;
+}
+
+
+extern const char ia32_emul_path[];
+int ia32_emul_find(struct thread *, caddr_t *, const char *, char *,
+ char **, int);
+
+#define CHECKALT(p, sgp, path, i) \
+ do { \
+ int _error; \
+ \
+ _error = ia32_emul_find(p, sgp, ia32_emul_path, path, \
+ &path, i); \
+ if (_error == EFAULT) \
+ return (_error); \
+ } while (0)
+
+#define CHECKALTEXIST(p, sgp, path) CHECKALT((p), (sgp), (path), 0)
+#define CHECKALTCREAT(p, sgp, path) CHECKALT((p), (sgp), (path), 1)
diff --git a/sys/amd64/ia32/syscalls.master b/sys/amd64/ia32/syscalls.master
index 347196a3da99..6de1c57b3665 100644
--- a/sys/amd64/ia32/syscalls.master
+++ b/sys/amd64/ia32/syscalls.master
@@ -36,6 +36,9 @@
#include <sys/param.h>
#include <sys/sysent.h>
#include <sys/sysproto.h>
+#include <sys/mount.h>
+#include <ia64/ia32/ia32.h>
+#include <ia64/ia32/ia32_proto.h>
; Reserved/unimplemented system calls in the range 0-150 inclusive
; are reserved for use in future Berkeley releases.
@@ -43,200 +46,189 @@
; redistributions should be placed in the reserved range at the end
; of the current calls.
-0 STD NOHIDE { int nosys(void); } syscall nosys_args int
-1 MSTD NOHIDE { void sys_exit(int rval); } exit sys_exit_args void
-2 MSTD POSIX { int fork(void); }
-3 MSTD POSIX { ssize_t read(int fd, void *buf, size_t nbyte); }
-4 MSTD POSIX { ssize_t write(int fd, const void *buf, size_t nbyte); }
-5 STD POSIX { int open(char *path, int flags, int mode); }
+0 MNOPROTO NOHIDE { int nosys(void); } syscall nosys_args int
+1 MNOPROTO NOHIDE { void sys_exit(int rval); } exit sys_exit_args void
+2 MNOPROTO POSIX { int fork(void); }
+3 MNOPROTO POSIX { ssize_t read(int fd, void *buf, size_t nbyte); }
+4 MNOPROTO POSIX { ssize_t write(int fd, const void *buf, size_t nbyte); }
+5 STD POSIX { int ia32_open(char *path, int flags, int mode); }
; XXX should be { int open(const char *path, int flags, ...); }
; but we're not ready for `const' or varargs.
; XXX man page says `mode_t mode'.
-6 MSTD POSIX { int close(int fd); }
-7 MSTD BSD { int wait4(int pid, int *status, int options, \
- struct rusage *rusage); } wait4 wait_args int
-8 COMPAT BSD { int creat(char *path, int mode); }
-9 STD POSIX { int link(char *path, char *link); }
-10 STD POSIX { int unlink(char *path); }
+6 MNOPROTO POSIX { int close(int fd); }
+7 MSTD BSD { int ia32_wait4(int pid, int *status, int options, \
+ struct rusage32 *rusage); }
+8 OBSOL BSD old creat
+9 NOPROTO POSIX { int link(char *path, char *link); }
+10 NOPROTO POSIX { int unlink(char *path); }
11 OBSOL NOHIDE execv
-12 STD POSIX { int chdir(char *path); }
-13 STD BSD { int fchdir(int fd); }
-14 STD POSIX { int mknod(char *path, int mode, int dev); }
-15 STD POSIX { int chmod(char *path, int mode); }
-16 STD POSIX { int chown(char *path, int uid, int gid); }
-17 MSTD BSD { int obreak(char *nsize); } break obreak_args int
-18 STD BSD { int getfsstat(struct statfs *buf, long bufsize, \
- int flags); }
-19 COMPAT POSIX { long lseek(int fd, long offset, int whence); }
-20 MSTD POSIX { pid_t getpid(void); }
-21 STD BSD { int mount(char *type, char *path, int flags, \
+12 NOPROTO POSIX { int chdir(char *path); }
+13 NOPROTO BSD { int fchdir(int fd); }
+14 NOPROTO POSIX { int mknod(char *path, int mode, int dev); }
+15 NOPROTO POSIX { int chmod(char *path, int mode); }
+16 NOPROTO POSIX { int chown(char *path, int uid, int gid); }
+17 MNOPROTO BSD { int obreak(char *nsize); } break obreak_args int
+18 STD BSD { int ia32_getfsstat(struct statfs32 *buf, \
+ long bufsize, int flags); }
+19 OBSOL POSIX olseek
+20 MNOPROTO POSIX { pid_t getpid(void); }
+21 NOPROTO BSD { int mount(char *type, char *path, int flags, \
caddr_t data); }
; XXX `path' should have type `const char *' but we're not ready for that.
-22 STD BSD { int unmount(char *path, int flags); }
-23 MSTD POSIX { int setuid(uid_t uid); }
-24 MSTD POSIX { uid_t getuid(void); }
-25 MSTD POSIX { uid_t geteuid(void); }
-26 STD BSD { int ptrace(int req, pid_t pid, caddr_t addr, \
+22 NOPROTO BSD { int unmount(char *path, int flags); }
+23 MNOPROTO POSIX { int setuid(uid_t uid); }
+24 MNOPROTO POSIX { uid_t getuid(void); }
+25 MNOPROTO POSIX { uid_t geteuid(void); }
+26 NOPROTO BSD { int ptrace(int req, pid_t pid, caddr_t addr, \
int data); }
-27 MSTD BSD { int recvmsg(int s, struct msghdr *msg, int flags); }
-28 MSTD BSD { int sendmsg(int s, caddr_t msg, int flags); }
-29 MSTD BSD { int recvfrom(int s, caddr_t buf, size_t len, \
+27 UNIMPL BSD recvmsg
+28 MNOPROTO BSD { int sendmsg(int s, caddr_t msg, int flags); }
+29 MNOPROTO BSD { int recvfrom(int s, caddr_t buf, size_t len, \
int flags, caddr_t from, int *fromlenaddr); }
-30 MSTD BSD { int accept(int s, caddr_t name, int *anamelen); }
-31 MSTD BSD { int getpeername(int fdes, caddr_t asa, int *alen); }
-32 MSTD BSD { int getsockname(int fdes, caddr_t asa, int *alen); }
-33 STD POSIX { int access(char *path, int flags); }
-34 STD BSD { int chflags(char *path, int flags); }
-35 STD BSD { int fchflags(int fd, int flags); }
-36 STD BSD { int sync(void); }
-37 MSTD POSIX { int kill(int pid, int signum); }
-38 COMPAT POSIX { int stat(char *path, struct ostat *ub); }
-39 MSTD POSIX { pid_t getppid(void); }
-40 COMPAT POSIX { int lstat(char *path, struct ostat *ub); }
-41 STD POSIX { int dup(u_int fd); }
-42 STD POSIX { int pipe(void); }
-43 MSTD POSIX { gid_t getegid(void); }
-44 MSTD BSD { int profil(caddr_t samples, size_t size, \
+30 MNOPROTO BSD { int accept(int s, caddr_t name, int *anamelen); }
+31 MNOPROTO BSD { int getpeername(int fdes, caddr_t asa, int *alen); }
+32 MNOPROTO BSD { int getsockname(int fdes, caddr_t asa, int *alen); }
+33 STD POSIX { int ia32_access(char *path, int flags); }
+34 STD BSD { int ia32_chflags(char *path, int flags); }
+35 NOPROTO BSD { int fchflags(int fd, int flags); }
+36 NOPROTO BSD { int sync(void); }
+37 MNOPROTO POSIX { int kill(int pid, int signum); }
+38 UNIMPL POSIX ostat
+39 MNOPROTO POSIX { pid_t getppid(void); }
+40 UNIMPL POSIX olstat
+41 NOPROTO POSIX { int dup(u_int fd); }
+42 NOPROTO POSIX { int pipe(void); }
+43 MNOPROTO POSIX { gid_t getegid(void); }
+44 MNOPROTO BSD { int profil(caddr_t samples, size_t size, \
size_t offset, u_int scale); }
-45 STD BSD { int ktrace(const char *fname, int ops, int facs, \
+45 NOPROTO BSD { int ktrace(const char *fname, int ops, int facs, \
int pid); }
-46 MCOMPAT POSIX { int sigaction(int signum, struct osigaction *nsa, \
- struct osigaction *osa); }
-47 MSTD POSIX { gid_t getgid(void); }
-48 MCOMPAT POSIX { int sigprocmask(int how, osigset_t mask); }
-; XXX note nonstandard (bogus) calling convention - the libc stub passes
-; us the mask, not a pointer to it, and we return the old mask as the
-; (int) return value.
-49 MSTD BSD { int getlogin(char *namebuf, u_int namelen); }
-50 MSTD BSD { int setlogin(char *namebuf); }
-51 MSTD BSD { int acct(char *path); }
-52 MCOMPAT POSIX { int sigpending(void); }
-53 MSTD BSD { int sigaltstack(stack_t *ss, stack_t *oss); }
-54 MSTD POSIX { int ioctl(int fd, u_long com, caddr_t data); }
-55 MSTD BSD { int reboot(int opt); }
-56 STD POSIX { int revoke(char *path); }
-57 STD POSIX { int symlink(char *path, char *link); }
-58 STD POSIX { int readlink(char *path, char *buf, int count); }
-59 MSTD POSIX { int execve(char *fname, char **argv, char **envv); }
-60 MSTD POSIX { int umask(int newmask); } umask umask_args int
-61 STD BSD { int chroot(char *path); }
-62 MCOMPAT POSIX { int fstat(int fd, struct ostat *sb); }
-63 MCOMPAT BSD { int getkerninfo(int op, char *where, size_t *size, \
- int arg); } getkerninfo getkerninfo_args int
-64 MCOMPAT BSD { int getpagesize(void); } \
- getpagesize getpagesize_args int
-65 STD BSD { int msync(void *addr, size_t len, int flags); }
-66 MSTD BSD { int vfork(void); }
+46 UNIMPL POSIX osigaction
+47 MNOPROTO POSIX { gid_t getgid(void); }
+48 UNIMPL POSIX osigprocmask
+49 MNOPROTO BSD { int getlogin(char *namebuf, u_int namelen); }
+50 MNOPROTO BSD { int setlogin(char *namebuf); }
+51 MNOPROTO BSD { int acct(char *path); }
+52 MNOPROTO POSIX { int sigpending(void); }
+53 STD BSD { int ia32_sigaltstack(struct sigaltstack32 *ss, struct sigaltstack32 *oss); }
+54 MNOPROTO POSIX { int ioctl(int fd, u_long com, caddr_t data); }
+55 MNOPROTO BSD { int reboot(int opt); }
+56 NOPROTO POSIX { int revoke(char *path); }
+57 NOPROTO POSIX { int symlink(char *path, char *link); }
+58 NOPROTO POSIX { int readlink(char *path, char *buf, int count); }
+59 STD POSIX { int ia32_execve(char *fname, u_int32_t *argv, u_int32_t *envv); }
+60 MNOPROTO POSIX { int umask(int newmask); } umask umask_args int
+61 NOPROTO BSD { int chroot(char *path); }
+62 OBSOL POSIX ofstat
+63 OBSOL BSD ogetkerninfo
+64 OBSOL BSD ogetpagesize
+65 OBSOL BSD omsync
+66 OBSOL BSD ovfork
67 OBSOL NOHIDE vread
68 OBSOL NOHIDE vwrite
-69 MSTD BSD { int sbrk(int incr); }
-70 MSTD BSD { int sstk(int incr); }
-71 MCOMPAT BSD { int mmap(void *addr, int len, int prot, \
- int flags, int fd, long pos); }
-72 MSTD BSD { int ovadvise(int anom); } vadvise ovadvise_args int
-73 MSTD BSD { int munmap(void *addr, size_t len); }
-74 MSTD BSD { int mprotect(const void *addr, size_t len, int prot); }
-75 MSTD BSD { int madvise(void *addr, size_t len, int behav); }
+69 MNOPROTO BSD { int sbrk(int incr); }
+70 MNOPROTO BSD { int sstk(int incr); }
+71 OBSOL BSD ommap
+72 MNOPROTO BSD { int ovadvise(int anom); } vadvise ovadvise_args int
+73 MNOPROTO BSD { int munmap(void *addr, size_t len); }
+74 MNOPROTO BSD { int mprotect(const void *addr, size_t len, int prot); }
+75 MNOPROTO BSD { int madvise(void *addr, size_t len, int behav); }
76 OBSOL NOHIDE vhangup
77 OBSOL NOHIDE vlimit
-78 MSTD BSD { int mincore(const void *addr, size_t len, \
+78 MNOPROTO BSD { int mincore(const void *addr, size_t len, \
char *vec); }
-79 MSTD POSIX { int getgroups(u_int gidsetsize, gid_t *gidset); }
-80 MSTD POSIX { int setgroups(u_int gidsetsize, gid_t *gidset); }
-81 MSTD POSIX { int getpgrp(void); }
-82 MSTD POSIX { int setpgid(int pid, int pgid); }
-83 MSTD BSD { int setitimer(u_int which, struct itimerval *itv, \
- struct itimerval *oitv); }
-84 MCOMPAT BSD { int wait(void); }
-85 MSTD BSD { int swapon(char *name); }
-86 MSTD BSD { int getitimer(u_int which, struct itimerval *itv); }
-87 MCOMPAT BSD { int gethostname(char *hostname, u_int len); } \
- gethostname gethostname_args int
-88 MCOMPAT BSD { int sethostname(char *hostname, u_int len); } \
- sethostname sethostname_args int
-89 MSTD BSD { int getdtablesize(void); }
-90 MSTD POSIX { int dup2(u_int from, u_int to); }
+79 MNOPROTO POSIX { int getgroups(u_int gidsetsize, gid_t *gidset); }
+80 MNOPROTO POSIX { int setgroups(u_int gidsetsize, gid_t *gidset); }
+81 MNOPROTO POSIX { int getpgrp(void); }
+82 MNOPROTO POSIX { int setpgid(int pid, int pgid); }
+83 STD BSD { int ia32_setitimer(u_int which, \
+ struct itimerval32 *itv, \
+ struct itimerval32 *oitv); }
+84 OBSOL BSD owait
+85 OBSOL BSD oswapon
+86 OBSOL BSD ogetitimer
+87 OBSOL BSD ogethostname
+88 OBSOL BSD osethostname
+89 MNOPROTO BSD { int getdtablesize(void); }
+90 MNOPROTO POSIX { int dup2(u_int from, u_int to); }
91 UNIMPL BSD getdopt
-92 MSTD POSIX { int fcntl(int fd, int cmd, long arg); }
+92 MNOPROTO POSIX { int fcntl(int fd, int cmd, long arg); }
; XXX should be { int fcntl(int fd, int cmd, ...); }
; but we're not ready for varargs.
; XXX man page says `int arg' too.
-93 MSTD BSD { int select(int nd, fd_set *in, fd_set *ou, \
- fd_set *ex, struct timeval *tv); }
+93 STD BSD { int ia32_select(int nd, fd_set *in, fd_set *ou, \
+ fd_set *ex, struct timeval32 *tv); }
+; XXX need to override for big-endian - little-endian should work fine.
94 UNIMPL BSD setdopt
-95 STD POSIX { int fsync(int fd); }
-96 MSTD BSD { int setpriority(int which, int who, int prio); }
-97 MSTD BSD { int socket(int domain, int type, int protocol); }
-98 MSTD BSD { int connect(int s, caddr_t name, int namelen); }
-99 MCPT_NOA BSD { int accept(int s, caddr_t name, int *anamelen); } \
+95 NOPROTO POSIX { int fsync(int fd); }
+96 MNOPROTO BSD { int setpriority(int which, int who, int prio); }
+97 MNOPROTO BSD { int socket(int domain, int type, int protocol); }
+98 MNOPROTO BSD { int connect(int s, caddr_t name, int namelen); }
+99 MNOPROTO BSD { int accept(int s, caddr_t name, int *anamelen); } \
accept accept_args int
-100 MSTD BSD { int getpriority(int which, int who); }
-101 MCOMPAT BSD { int send(int s, caddr_t buf, int len, int flags); }
-102 MCOMPAT BSD { int recv(int s, caddr_t buf, int len, int flags); }
-103 STD BSD { int osigreturn(struct osigcontext *sigcntxp); }
-104 MSTD BSD { int bind(int s, caddr_t name, int namelen); }
-105 MSTD BSD { int setsockopt(int s, int level, int name, \
+100 MNOPROTO BSD { int getpriority(int which, int who); }
+101 OBSOL BSD osend
+102 OBSOL BSD orecv
+103 OBSOL BSD osigreturn
+104 MNOPROTO BSD { int bind(int s, caddr_t name, int namelen); }
+105 MNOPROTO BSD { int setsockopt(int s, int level, int name, \
caddr_t val, int valsize); }
-106 MSTD BSD { int listen(int s, int backlog); }
+106 MNOPROTO BSD { int listen(int s, int backlog); }
107 OBSOL NOHIDE vtimes
-108 MCOMPAT BSD { int sigvec(int signum, struct sigvec *nsv, \
- struct sigvec *osv); }
-109 MCOMPAT BSD { int sigblock(int mask); }
-110 MCOMPAT BSD { int sigsetmask(int mask); }
-111 MCOMPAT POSIX { int sigsuspend(osigset_t mask); }
-; XXX note nonstandard (bogus) calling convention - the libc stub passes
-; us the mask, not a pointer to it.
-112 MCOMPAT BSD { int sigstack(struct sigstack *nss, \
- struct sigstack *oss); }
-113 MCOMPAT BSD { int recvmsg(int s, struct omsghdr *msg, int flags); }
-114 MCOMPAT BSD { int sendmsg(int s, caddr_t msg, int flags); }
+108 OBSOL BSD osigvec
+109 OBSOL BSD osigblock
+110 OBSOL BSD osigsetmask
+111 OBSOL POSIX osigsuspend
+112 OBSOL BSD osigstack
+113 OBSOL BSD orecvmsg
+114 OBSOL BSD osendmsg
115 OBSOL NOHIDE vtrace
-116 MSTD BSD { int gettimeofday(struct timeval *tp, \
+116 STD BSD { int ia32_gettimeofday(struct timeval32 *tp, \
struct timezone *tzp); }
-117 MSTD BSD { int getrusage(int who, struct rusage *rusage); }
-118 MSTD BSD { int getsockopt(int s, int level, int name, \
+117 STD BSD { int ia32_getrusage(int who, struct rusage32 *rusage); }
+118 MNOPROTO BSD { int getsockopt(int s, int level, int name, \
caddr_t val, int *avalsize); }
119 UNIMPL NOHIDE resuba (BSD/OS 2.x)
-120 MSTD BSD { int readv(int fd, struct iovec *iovp, u_int iovcnt); }
-121 MSTD BSD { int writev(int fd, struct iovec *iovp, \
+120 STD BSD { int ia32_readv(int fd, struct iovec32 *iovp, u_int iovcnt); }
+121 STD BSD { int ia32_writev(int fd, struct iovec32 *iovp, \
u_int iovcnt); }
-122 MSTD BSD { int settimeofday(struct timeval *tv, \
+122 STD BSD { int ia32_settimeofday(struct timeval32 *tv, \
struct timezone *tzp); }
-123 STD BSD { int fchown(int fd, int uid, int gid); }
-124 STD BSD { int fchmod(int fd, int mode); }
-125 MCPT_NOA BSD { int recvfrom(int s, caddr_t buf, size_t len, \
+123 NOPROTO BSD { int fchown(int fd, int uid, int gid); }
+124 NOPROTO BSD { int fchmod(int fd, int mode); }
+125 MNOPROTO BSD { int recvfrom(int s, caddr_t buf, size_t len, \
int flags, caddr_t from, int *fromlenaddr); } \
recvfrom recvfrom_args int
-126 MSTD BSD { int setreuid(int ruid, int euid); }
-127 MSTD BSD { int setregid(int rgid, int egid); }
-128 STD POSIX { int rename(char *from, char *to); }
-129 COMPAT BSD { int truncate(char *path, long length); }
-130 COMPAT BSD { int ftruncate(int fd, long length); }
-131 MSTD BSD { int flock(int fd, int how); }
-132 STD POSIX { int mkfifo(char *path, int mode); }
-133 MSTD BSD { int sendto(int s, caddr_t buf, size_t len, \
+126 MNOPROTO BSD { int setreuid(int ruid, int euid); }
+127 MNOPROTO BSD { int setregid(int rgid, int egid); }
+128 NOPROTO POSIX { int rename(char *from, char *to); }
+129 OBSOL BSD otruncate
+130 OBSOL BSD ftruncate
+131 MNOPROTO BSD { int flock(int fd, int how); }
+132 NOPROTO POSIX { int mkfifo(char *path, int mode); }
+133 MNOPROTO BSD { int sendto(int s, caddr_t buf, size_t len, \
int flags, caddr_t to, int tolen); }
-134 MSTD BSD { int shutdown(int s, int how); }
-135 MSTD BSD { int socketpair(int domain, int type, int protocol, \
+134 MNOPROTO BSD { int shutdown(int s, int how); }
+135 MNOPROTO BSD { int socketpair(int domain, int type, int protocol, \
int *rsv); }
-136 STD POSIX { int mkdir(char *path, int mode); }
-137 STD POSIX { int rmdir(char *path); }
-138 STD BSD { int utimes(char *path, struct timeval *tptr); }
+136 NOPROTO POSIX { int mkdir(char *path, int mode); }
+137 NOPROTO POSIX { int rmdir(char *path); }
+138 STD BSD { int ia32_utimes(char *path, \
+ struct timeval32 *tptr); }
139 OBSOL NOHIDE 4.2 sigreturn
-140 MSTD BSD { int adjtime(struct timeval *delta, \
- struct timeval *olddelta); }
-141 MCOMPAT BSD { int getpeername(int fdes, caddr_t asa, int *alen); }
-142 MCOMPAT BSD { long gethostid(void); }
-143 MCOMPAT BSD { int sethostid(long hostid); }
-144 MCOMPAT BSD { int getrlimit(u_int which, struct orlimit *rlp); }
-145 MCOMPAT BSD { int setrlimit(u_int which, struct orlimit *rlp); }
-146 MCOMPAT BSD { int killpg(int pgid, int signum); }
-147 MSTD POSIX { int setsid(void); }
-148 STD BSD { int quotactl(char *path, int cmd, int uid, \
+140 STD BSD { int ia32_adjtime(struct timeval32 *delta, \
+ struct timeval32 *olddelta); }
+141 OBSOL BSD ogetpeername
+142 OBSOL BSD ogethostid
+143 OBSOL BSD sethostid
+144 OBSOL BSD getrlimit
+145 OBSOL BSD setrlimit
+146 OBSOL BSD killpg
+147 MNOPROTO POSIX { int setsid(void); }
+148 NOPROTO BSD { int quotactl(char *path, int cmd, int uid, \
caddr_t arg); }
-149 MCOMPAT BSD { int quota(void); }
-150 MCPT_NOA BSD { int getsockname(int fdec, caddr_t asa, int *alen); }\
- getsockname getsockname_args int
+149 OBSOL BSD oquota
+150 OBSOL BSD ogetsockname
; Syscalls 151-180 inclusive are reserved for vendor-specific
; system calls. (This includes various calls added for compatibity
@@ -247,136 +239,138 @@
153 UNIMPL NOHIDE asyncdaemon (BSD/OS 2.x)
154 UNIMPL NOHIDE nosys
; 155 is initialized by the NFS code, if present.
-155 MNOIMPL BSD { int nfssvc(int flag, caddr_t argp); }
-156 COMPAT BSD { int getdirentries(int fd, char *buf, u_int count, \
+155 UNIMPL NOHIDE nfssvc
+156 NOPROTO BSD { int getdirentries(int fd, char *buf, u_int count, \
long *basep); }
-157 STD BSD { int statfs(char *path, struct statfs *buf); }
-158 STD BSD { int fstatfs(int fd, struct statfs *buf); }
+157 STD BSD { int ia32_statfs(char *path, struct statfs32 *buf); }
+158 STD BSD { int ia32_fstatfs(int fd, struct statfs32 *buf); }
159 UNIMPL NOHIDE nosys
160 UNIMPL NOHIDE nosys
-161 STD BSD { int getfh(char *fname, struct fhandle *fhp); }
-162 MSTD BSD { int getdomainname(char *domainname, int len); }
-163 MSTD BSD { int setdomainname(char *domainname, int len); }
-164 MSTD BSD { int uname(struct utsname *name); }
-165 STD BSD { int sysarch(int op, char *parms); }
-166 MSTD BSD { int rtprio(int function, pid_t pid, \
+161 NOPROTO BSD { int getfh(char *fname, struct fhandle *fhp); }
+162 MNOPROTO BSD { int getdomainname(char *domainname, int len); }
+163 MNOPROTO BSD { int setdomainname(char *domainname, int len); }
+164 MNOPROTO BSD { int uname(struct utsname *name); }
+165 NOPROTO BSD { int sysarch(int op, char *parms); }
+166 MNOPROTO BSD { int rtprio(int function, pid_t pid, \
struct rtprio *rtp); }
167 UNIMPL NOHIDE nosys
168 UNIMPL NOHIDE nosys
-; 169 is initialized by the SYSVSEM code if present or loaded
-169 MNOSTD BSD { int semsys(int which, int a2, int a3, int a4, \
+169 STD BSD { int ia32_semsys(int which, int a2, int a3, int a4, \
int a5); }
-; 169 is initialized by the SYSVMSG code if present or loaded
-; XXX should be { int semsys(int which, ...); }
-170 MNOSTD BSD { int msgsys(int which, int a2, int a3, int a4, \
+170 STD BSD { int ia32_msgsys(int which, int a2, int a3, int a4, \
int a5, int a6); }
-; 169 is initialized by the SYSVSHM code if present or loaded
-; XXX should be { int msgsys(int which, ...); }
-171 MNOSTD BSD { int shmsys(int which, int a2, int a3, int a4); }
-; XXX should be { int shmsys(int which, ...); }
+171 STD BSD { int ia32_shmsys(int which, int a2, int a3, int a4); }
172 UNIMPL NOHIDE nosys
-173 MSTD POSIX { ssize_t pread(int fd, void *buf, size_t nbyte, \
- int pad, off_t offset); }
-174 MSTD POSIX { ssize_t pwrite(int fd, const void *buf, \
- size_t nbyte, int pad, off_t offset); }
+173 STD POSIX { ssize_t ia32_pread(int fd, void *buf, size_t nbyte, \
+ int pad, u_int32_t offsetlo, u_int32_t offsethi); }
+; XXX note - bigendian is different
+174 STD POSIX { ssize_t ia32_pwrite(int fd, const void *buf, \
+ size_t nbyte, int pad, u_int32_t offsetlo, \
+ u_int32_t offsethi); }
+; XXX note - bigendian is different
175 UNIMPL NOHIDE nosys
-176 MSTD BSD { int ntp_adjtime(struct timex *tp); }
+176 MNOPROTO BSD { int ntp_adjtime(struct timex *tp); }
177 UNIMPL NOHIDE sfork (BSD/OS 2.x)
178 UNIMPL NOHIDE getdescriptor (BSD/OS 2.x)
179 UNIMPL NOHIDE setdescriptor (BSD/OS 2.x)
180 UNIMPL NOHIDE nosys
; Syscalls 181-199 are used by/reserved for BSD
-181 MSTD POSIX { int setgid(gid_t gid); }
-182 MSTD BSD { int setegid(gid_t egid); }
-183 MSTD BSD { int seteuid(uid_t euid); }
+181 MNOPROTO POSIX { int setgid(gid_t gid); }
+182 MNOPROTO BSD { int setegid(gid_t egid); }
+183 MNOPROTO BSD { int seteuid(uid_t euid); }
184 UNIMPL BSD lfs_bmapv
185 UNIMPL BSD lfs_markv
186 UNIMPL BSD lfs_segclean
187 UNIMPL BSD lfs_segwait
-188 STD POSIX { int stat(char *path, struct stat *ub); }
-189 MSTD POSIX { int fstat(int fd, struct stat *sb); }
-190 STD POSIX { int lstat(char *path, struct stat *ub); }
-191 STD POSIX { int pathconf(char *path, int name); }
-192 MSTD POSIX { int fpathconf(int fd, int name); }
+188 STD POSIX { int ia32_stat(char *path, struct stat32 *ub); }
+189 STD POSIX { int ia32_fstat(int fd, struct stat32 *ub); }
+190 STD POSIX { int ia32_lstat(char *path, struct stat32 *ub); }
+191 NOPROTO POSIX { int pathconf(char *path, int name); }
+192 MNOPROTO POSIX { int fpathconf(int fd, int name); }
193 UNIMPL NOHIDE nosys
-194 MSTD BSD { int getrlimit(u_int which, \
+194 MNOPROTO BSD { int getrlimit(u_int which, \
struct rlimit *rlp); } \
getrlimit __getrlimit_args int
-195 MSTD BSD { int setrlimit(u_int which, \
+195 MNOPROTO BSD { int setrlimit(u_int which, \
struct rlimit *rlp); } \
setrlimit __setrlimit_args int
-196 STD BSD { int getdirentries(int fd, char *buf, u_int count, \
+196 NOPROTO BSD { int getdirentries(int fd, char *buf, u_int count, \
long *basep); }
-197 MSTD BSD { caddr_t mmap(caddr_t addr, size_t len, int prot, \
- int flags, int fd, int pad, off_t pos); }
-198 STD NOHIDE { int nosys(void); } __syscall __syscall_args int
-199 STD POSIX { off_t lseek(int fd, int pad, off_t offset, \
+197 STD BSD { caddr_t ia32_mmap(caddr_t addr, size_t len, \
+ int prot, int flags, int fd, int pad, \
+ u_int32_t poslo, u_int32_t poshi); }
+198 NOPROTO NOHIDE { int nosys(void); } __syscall __syscall_args int
+; XXX note - bigendian is different
+199 STD POSIX { off_t ia32_lseek(int fd, int pad, \
+ u_int32_t offsetlo, u_int32_t offsethi, \
int whence); }
-200 STD BSD { int truncate(char *path, int pad, off_t length); }
-201 STD BSD { int ftruncate(int fd, int pad, off_t length); }
-202 MSTD BSD { int __sysctl(int *name, u_int namelen, void *old, \
- size_t *oldlenp, void *new, size_t newlen); } \
- __sysctl sysctl_args int
-; properly, __sysctl should be a NOHIDE, but making an exception
-; here allows to avoid one in libc/sys/Makefile.inc.
-203 MSTD BSD { int mlock(const void *addr, size_t len); }
-204 MSTD BSD { int munlock(const void *addr, size_t len); }
-205 STD BSD { int undelete(char *path); }
-206 STD BSD { int futimes(int fd, struct timeval *tptr); }
-207 MSTD BSD { int getpgid(pid_t pid); }
+; XXX note - bigendian is different
+200 STD BSD { int ia32_truncate(char *path, int pad, \
+ u_int32_t lengthlo, u_int32_t lengthhi); }
+; XXX note - bigendian is different
+201 STD BSD { int ia32_ftruncate(int fd, int pad, \
+ u_int32_t lengthlo, u_int32_t lengthhi); }
+202 MSTD BSD { int ia32_sysctl(int *name, u_int namelen, \
+ void *old, u_int32_t *oldlenp, void *new, \
+ u_int32_t newlen); }
+203 MNOPROTO BSD { int mlock(const void *addr, size_t len); }
+204 MNOPROTO BSD { int munlock(const void *addr, size_t len); }
+205 NOPROTO BSD { int undelete(char *path); }
+206 NOPROTO BSD { int futimes(int fd, struct timeval *tptr); }
+207 MNOPROTO BSD { int getpgid(pid_t pid); }
208 UNIMPL NOHIDE newreboot (NetBSD)
-209 MSTD BSD { int poll(struct pollfd *fds, u_int nfds, \
+209 MNOPROTO BSD { int poll(struct pollfd *fds, u_int nfds, \
int timeout); }
;
; The following are reserved for loadable syscalls
;
-210 NODEF NOHIDE lkmnosys lkmnosys nosys_args int
-211 NODEF NOHIDE lkmnosys lkmnosys nosys_args int
-212 NODEF NOHIDE lkmnosys lkmnosys nosys_args int
-213 NODEF NOHIDE lkmnosys lkmnosys nosys_args int
-214 NODEF NOHIDE lkmnosys lkmnosys nosys_args int
-215 NODEF NOHIDE lkmnosys lkmnosys nosys_args int
-216 NODEF NOHIDE lkmnosys lkmnosys nosys_args int
-217 NODEF NOHIDE lkmnosys lkmnosys nosys_args int
-218 NODEF NOHIDE lkmnosys lkmnosys nosys_args int
-219 NODEF NOHIDE lkmnosys lkmnosys nosys_args int
+210 UNIMPL NOHIDE
+211 UNIMPL NOHIDE
+212 UNIMPL NOHIDE
+213 UNIMPL NOHIDE
+214 UNIMPL NOHIDE
+215 UNIMPL NOHIDE
+216 UNIMPL NOHIDE
+217 UNIMPL NOHIDE
+218 UNIMPL NOHIDE
+219 UNIMPL NOHIDE
;
; The following were introduced with NetBSD/4.4Lite-2
; They are initialized by thier respective modules/sysinits
-220 MNOSTD BSD { int __semctl(int semid, int semnum, int cmd, \
+220 MNOPROTO BSD { int __semctl(int semid, int semnum, int cmd, \
union semun *arg); }
-221 MNOSTD BSD { int semget(key_t key, int nsems, int semflg); }
-222 MNOSTD BSD { int semop(int semid, struct sembuf *sops, \
+221 MNOPROTO BSD { int semget(key_t key, int nsems, int semflg); }
+222 MNOPROTO BSD { int semop(int semid, struct sembuf *sops, \
u_int nsops); }
223 UNIMPL NOHIDE semconfig
-224 MNOSTD BSD { int msgctl(int msqid, int cmd, \
+224 MNOPROTO BSD { int msgctl(int msqid, int cmd, \
struct msqid_ds *buf); }
-225 MNOSTD BSD { int msgget(key_t key, int msgflg); }
-226 MNOSTD BSD { int msgsnd(int msqid, void *msgp, size_t msgsz, \
+225 MNOPROTO BSD { int msgget(key_t key, int msgflg); }
+226 MNOPROTO BSD { int msgsnd(int msqid, void *msgp, size_t msgsz, \
int msgflg); }
-227 MNOSTD BSD { int msgrcv(int msqid, void *msgp, size_t msgsz, \
+227 MNOPROTO BSD { int msgrcv(int msqid, void *msgp, size_t msgsz, \
long msgtyp, int msgflg); }
-228 MNOSTD BSD { int shmat(int shmid, void *shmaddr, int shmflg); }
-229 MNOSTD BSD { int shmctl(int shmid, int cmd, \
+228 MNOPROTO BSD { int shmat(int shmid, void *shmaddr, int shmflg); }
+229 MNOPROTO BSD { int shmctl(int shmid, int cmd, \
struct shmid_ds *buf); }
-230 MNOSTD BSD { int shmdt(void *shmaddr); }
-231 MNOSTD BSD { int shmget(key_t key, int size, int shmflg); }
+230 MNOPROTO BSD { int shmdt(void *shmaddr); }
+231 MNOPROTO BSD { int shmget(key_t key, int size, int shmflg); }
;
-232 MSTD POSIX { int clock_gettime(clockid_t clock_id, \
+232 MNOPROTO POSIX { int clock_gettime(clockid_t clock_id, \
struct timespec *tp); }
-233 MSTD POSIX { int clock_settime(clockid_t clock_id, \
+233 MNOPROTO POSIX { int clock_settime(clockid_t clock_id, \
const struct timespec *tp); }
-234 MSTD POSIX { int clock_getres(clockid_t clock_id, \
+234 MNOPROTO POSIX { int clock_getres(clockid_t clock_id, \
struct timespec *tp); }
235 UNIMPL NOHIDE timer_create
236 UNIMPL NOHIDE timer_delete
237 UNIMPL NOHIDE timer_settime
238 UNIMPL NOHIDE timer_gettime
239 UNIMPL NOHIDE timer_getoverrun
-240 MSTD POSIX { int nanosleep(const struct timespec *rqtp, \
+240 MNOPROTO POSIX { int nanosleep(const struct timespec *rqtp, \
struct timespec *rmtp); }
241 UNIMPL NOHIDE nosys
242 UNIMPL NOHIDE nosys
@@ -388,12 +382,12 @@
248 UNIMPL NOHIDE nosys
249 UNIMPL NOHIDE nosys
; syscall numbers initially used in OpenBSD
-250 MSTD BSD { int minherit(void *addr, size_t len, int inherit); }
-251 MSTD BSD { int rfork(int flags); }
-252 MSTD BSD { int openbsd_poll(struct pollfd *fds, u_int nfds, \
+250 MNOPROTO BSD { int minherit(void *addr, size_t len, int inherit); }
+251 MNOPROTO BSD { int rfork(int flags); }
+252 MNOPROTO BSD { int openbsd_poll(struct pollfd *fds, u_int nfds, \
int timeout); }
-253 STD BSD { int issetugid(void); }
-254 STD BSD { int lchown(char *path, int uid, int gid); }
+253 NOPROTO BSD { int issetugid(void); }
+254 NOPROTO BSD { int lchown(char *path, int uid, int gid); }
255 UNIMPL NOHIDE nosys
256 UNIMPL NOHIDE nosys
257 UNIMPL NOHIDE nosys
@@ -411,15 +405,15 @@
269 UNIMPL NOHIDE nosys
270 UNIMPL NOHIDE nosys
271 UNIMPL NOHIDE nosys
-272 STD BSD { int getdents(int fd, char *buf, size_t count); }
+272 NOPROTO BSD { int getdents(int fd, char *buf, size_t count); }
273 UNIMPL NOHIDE nosys
-274 STD BSD { int lchmod(char *path, mode_t mode); }
+274 NOPROTO BSD { int lchmod(char *path, mode_t mode); }
275 NOPROTO BSD { int lchown(char *path, uid_t uid, gid_t gid); } netbsd_lchown lchown_args int
-276 STD BSD { int lutimes(char *path, struct timeval *tptr); }
+276 NOPROTO BSD { int lutimes(char *path, struct timeval *tptr); }
277 MNOPROTO BSD { int msync(void *addr, size_t len, int flags); } netbsd_msync msync_args int
-278 STD BSD { int nstat(char *path, struct nstat *ub); }
-279 MSTD BSD { int nfstat(int fd, struct nstat *sb); }
-280 STD BSD { int nlstat(char *path, struct nstat *ub); }
+278 NOPROTO BSD { int nstat(char *path, struct nstat *ub); }
+279 MNOPROTO BSD { int nfstat(int fd, struct nstat *sb); }
+280 NOPROTO BSD { int nlstat(char *path, struct nstat *ub); }
281 UNIMPL NOHIDE nosys
282 UNIMPL NOHIDE nosys
283 UNIMPL NOHIDE nosys
@@ -437,126 +431,133 @@
295 UNIMPL NOHIDE nosys
296 UNIMPL NOHIDE nosys
; XXX 297 is 300 in NetBSD
-297 STD BSD { int fhstatfs(const struct fhandle *u_fhp, struct statfs *buf); }
-298 STD BSD { int fhopen(const struct fhandle *u_fhp, int flags); }
-299 STD BSD { int fhstat(const struct fhandle *u_fhp, struct stat *sb); }
+297 NOPROTO BSD { int fhstatfs(const struct fhandle *u_fhp, struct statfs *buf); }
+298 NOPROTO BSD { int fhopen(const struct fhandle *u_fhp, int flags); }
+299 NOPROTO BSD { int fhstat(const struct fhandle *u_fhp, struct stat *sb); }
; syscall numbers for FreeBSD
-300 MSTD BSD { int modnext(int modid); }
-301 MSTD BSD { int modstat(int modid, struct module_stat* stat); }
-302 MSTD BSD { int modfnext(int modid); }
-303 MSTD BSD { int modfind(const char *name); }
-304 MSTD BSD { int kldload(const char *file); }
-305 MSTD BSD { int kldunload(int fileid); }
-306 MSTD BSD { int kldfind(const char *file); }
-307 MSTD BSD { int kldnext(int fileid); }
-308 MSTD BSD { int kldstat(int fileid, struct kld_file_stat* stat); }
-309 MSTD BSD { int kldfirstmod(int fileid); }
-310 MSTD BSD { int getsid(pid_t pid); }
-311 MSTD BSD { int setresuid(uid_t ruid, uid_t euid, uid_t suid); }
-312 MSTD BSD { int setresgid(gid_t rgid, gid_t egid, gid_t sgid); }
+300 MNOPROTO BSD { int modnext(int modid); }
+301 MNOPROTO BSD { int modstat(int modid, struct module_stat* stat); }
+302 MNOPROTO BSD { int modfnext(int modid); }
+303 MNOPROTO BSD { int modfind(const char *name); }
+304 MNOPROTO BSD { int kldload(const char *file); }
+305 MNOPROTO BSD { int kldunload(int fileid); }
+306 MNOPROTO BSD { int kldfind(const char *file); }
+307 MNOPROTO BSD { int kldnext(int fileid); }
+308 MNOPROTO BSD { int kldstat(int fileid, struct kld_file_stat* stat); }
+309 MNOPROTO BSD { int kldfirstmod(int fileid); }
+310 MNOPROTO BSD { int getsid(pid_t pid); }
+311 MNOPROTO BSD { int setresuid(uid_t ruid, uid_t euid, uid_t suid); }
+312 MNOPROTO BSD { int setresgid(gid_t rgid, gid_t egid, gid_t sgid); }
313 OBSOL NOHIDE signanosleep
-314 NOSTD BSD { int aio_return(struct aiocb *aiocbp); }
-315 NOSTD BSD { int aio_suspend(struct aiocb * const * aiocbp, int nent, const struct timespec *timeout); }
-316 NOSTD BSD { int aio_cancel(int fd, struct aiocb *aiocbp); }
-317 NOSTD BSD { int aio_error(struct aiocb *aiocbp); }
-318 NOSTD BSD { int aio_read(struct aiocb *aiocbp); }
-319 NOSTD BSD { int aio_write(struct aiocb *aiocbp); }
-320 NOSTD BSD { int lio_listio(int mode, struct aiocb * const *acb_list, int nent, struct sigevent *sig); }
-321 MSTD BSD { int yield(void); }
+314 UNIMPL NOHIDE aio_return
+315 UNIMPL NOHIDE aio_suspend
+316 UNIMPL NOHIDE aio_cancel
+317 UNIMPL NOHIDE aio_error
+318 UNIMPL NOHIDE aio_read
+319 UNIMPL NOHIDE aio_write
+320 UNIMPL NOHIDE lio_listio
+321 MNOPROTO BSD { int yield(void); }
322 OBSOL NOHIDE thr_sleep
323 OBSOL NOHIDE thr_wakeup
-324 MSTD BSD { int mlockall(int how); }
-325 MSTD BSD { int munlockall(void); }
-326 STD BSD { int __getcwd(u_char *buf, u_int buflen); }
+324 MNOPROTO BSD { int mlockall(int how); }
+325 MNOPROTO BSD { int munlockall(void); }
+326 NOPROTO BSD { int __getcwd(u_char *buf, u_int buflen); }
-327 MSTD POSIX { int sched_setparam (pid_t pid, const struct sched_param *param); }
-328 MSTD POSIX { int sched_getparam (pid_t pid, struct sched_param *param); }
+327 MNOPROTO POSIX { int sched_setparam (pid_t pid, const struct sched_param *param); }
+328 MNOPROTO POSIX { int sched_getparam (pid_t pid, struct sched_param *param); }
-329 MSTD POSIX { int sched_setscheduler (pid_t pid, int policy, const struct sched_param *param); }
-330 MSTD POSIX { int sched_getscheduler (pid_t pid); }
+329 MNOPROTO POSIX { int sched_setscheduler (pid_t pid, int policy, const struct sched_param *param); }
+330 MNOPROTO POSIX { int sched_getscheduler (pid_t pid); }
-331 MSTD POSIX { int sched_yield (void); }
-332 MSTD POSIX { int sched_get_priority_max (int policy); }
-333 MSTD POSIX { int sched_get_priority_min (int policy); }
-334 MSTD POSIX { int sched_rr_get_interval (pid_t pid, struct timespec *interval); }
-335 STD BSD { int utrace(const void *addr, size_t len); }
-336 MSTD BSD { int sendfile(int fd, int s, off_t offset, size_t nbytes, \
- struct sf_hdtr *hdtr, off_t *sbytes, int flags); }
-337 STD BSD { int kldsym(int fileid, int cmd, void *data); }
-338 MSTD BSD { int jail(struct jail *jail); }
+331 MNOPROTO POSIX { int sched_yield (void); }
+332 MNOPROTO POSIX { int sched_get_priority_max (int policy); }
+333 MNOPROTO POSIX { int sched_get_priority_min (int policy); }
+334 MNOPROTO POSIX { int sched_rr_get_interval (pid_t pid, struct timespec *interval); }
+335 NOPROTO BSD { int utrace(const void *addr, size_t len); }
+; XXX note - bigendian is different
+336 MSTD BSD { int ia32_sendfile(int fd, int s, u_int32_t offsetlo, \
+ u_int32_t offsethi, size_t nbytes, \
+ struct sf_hdtr *hdtr, off_t *sbytes, int flags); }
+337 NOPROTO BSD { int kldsym(int fileid, int cmd, void *data); }
+338 MNOPROTO BSD { int jail(struct jail *jail); }
339 UNIMPL BSD pioctl
-340 MSTD POSIX { int sigprocmask(int how, const sigset_t *set, \
+340 MNOPROTO POSIX { int sigprocmask(int how, const sigset_t *set, \
sigset_t *oset); }
-341 MSTD POSIX { int sigsuspend(const sigset_t *sigmask); }
-342 MSTD POSIX { int sigaction(int sig, const struct sigaction *act, \
- struct sigaction *oact); }
-343 MSTD POSIX { int sigpending(sigset_t *set); }
-344 STD BSD { int sigreturn(const struct __ucontext *sigcntxp); }
+341 MNOPROTO POSIX { int sigsuspend(const sigset_t *sigmask); }
+342 STD POSIX { int ia32_sigaction(int sig, \
+ struct sigaction32 *act, \
+ struct sigaction32 *oact); }
+343 MNOPROTO POSIX { int sigpending(sigset_t *set); }
+344 MNOPROTO BSD { int sigreturn(const struct __ucontext *sigcntxp); }
345 UNIMPL NOHIDE sigtimedwait
346 UNIMPL NOHIDE sigwaitinfo
-347 MSTD BSD { int __acl_get_file(const char *path, \
+347 MNOPROTO BSD { int __acl_get_file(const char *path, \
acl_type_t type, struct acl *aclp); }
-348 MSTD BSD { int __acl_set_file(const char *path, \
+348 MNOPROTO BSD { int __acl_set_file(const char *path, \
acl_type_t type, struct acl *aclp); }
-349 MSTD BSD { int __acl_get_fd(int filedes, acl_type_t type, \
+349 MNOPROTO BSD { int __acl_get_fd(int filedes, acl_type_t type, \
struct acl *aclp); }
-350 MSTD BSD { int __acl_set_fd(int filedes, acl_type_t type, \
+350 MNOPROTO BSD { int __acl_set_fd(int filedes, acl_type_t type, \
struct acl *aclp); }
-351 MSTD BSD { int __acl_delete_file(const char *path, \
+351 MNOPROTO BSD { int __acl_delete_file(const char *path, \
acl_type_t type); }
-352 MSTD BSD { int __acl_delete_fd(int filedes, acl_type_t type); }
-353 MSTD BSD { int __acl_aclcheck_file(const char *path, \
+352 MNOPROTO BSD { int __acl_delete_fd(int filedes, acl_type_t type); }
+353 MNOPROTO BSD { int __acl_aclcheck_file(const char *path, \
acl_type_t type, struct acl *aclp); }
-354 MSTD BSD { int __acl_aclcheck_fd(int filedes, acl_type_t type, \
+354 MNOPROTO BSD { int __acl_aclcheck_fd(int filedes, acl_type_t type, \
struct acl *aclp); }
-355 STD BSD { int extattrctl(const char *path, int cmd, \
+355 NOPROTO BSD { int extattrctl(const char *path, int cmd, \
const char *filename, int attrnamespace, \
const char *attrname); }
-356 STD BSD { int extattr_set_file(const char *path, \
+356 NOPROTO BSD { int extattr_set_file(const char *path, \
int attrnamespace, const char *attrname, \
void *data, size_t nbytes); }
-357 STD BSD { ssize_t extattr_get_file(const char *path, \
+357 NOPROTO BSD { ssize_t extattr_get_file(const char *path, \
int attrnamespace, const char *attrname, \
void *data, size_t nbytes); }
-358 STD BSD { int extattr_delete_file(const char *path, \
+358 NOPROTO BSD { int extattr_delete_file(const char *path, \
int attrnamespace, const char *attrname); }
-359 NOSTD BSD { int aio_waitcomplete(struct aiocb **aiocbp, struct timespec *timeout); }
-360 MSTD BSD { int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); }
-361 MSTD BSD { int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); }
-362 MSTD BSD { int kqueue(void); }
-363 MSTD BSD { int kevent(int fd, \
+359 UNIMPL NOHIDE aio_waitcomplete
+360 MNOPROTO BSD { int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); }
+361 MNOPROTO BSD { int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); }
+362 MNOPROTO BSD { int kqueue(void); }
+363 MNOPROTO BSD { int kevent(int fd, \
const struct kevent *changelist, int nchanges, \
struct kevent *eventlist, int nevents, \
const struct timespec *timeout); }
-364 STD BSD { int __cap_get_proc(struct cap *cap_p); }
-365 STD BSD { int __cap_set_proc(struct cap *cap_p); }
-366 STD BSD { int __cap_get_fd(int fd, struct cap *cap_p); }
-367 STD BSD { int __cap_get_file(const char *path_p, struct cap *cap_p); }
-368 STD BSD { int __cap_set_fd(int fd, struct cap *cap_p); }
-369 STD BSD { int __cap_set_file(const char *path_p, struct cap *cap_p); }
-370 NODEF NOHIDE lkmressys lkmressys nosys_args int
-371 STD BSD { int extattr_set_fd(int fd, int attrnamespace, \
+364 UNIMPL NOHIDE __cap_get_proc
+365 UNIMPL NOHIDE __cap_set_proc
+366 UNIMPL NOHIDE __cap_get_fd
+367 UNIMPL NOHIDE __cap_get_file
+368 UNIMPL NOHIDE __cap_set_fd
+369 UNIMPL NOHIDE __cap_set_file
+370 UNIMPL NOHIDE lkmressys
+371 NOPROTO BSD { int extattr_set_fd(int fd, int attrnamespace, \
const char *attrname, void *data, \
size_t nbytes); }
-372 STD BSD { ssize_t extattr_get_fd(int fd, int attrnamespace, \
+372 NOPROTO BSD { ssize_t extattr_get_fd(int fd, int attrnamespace, \
const char *attrname, void *data, size_t nbytes); }
-373 STD BSD { int extattr_delete_fd(int fd, int attrnamespace, \
+373 NOPROTO BSD { int extattr_delete_fd(int fd, int attrnamespace, \
const char *attrname); }
-374 MSTD BSD { int __setugid(int flag); }
-375 NOIMPL BSD { int nfsclnt(int flag, caddr_t argp); }
-376 STD BSD { int eaccess(char *path, int flags); }
+374 MNOPROTO BSD { int __setugid(int flag); }
+375 UNIMPL BSD nfsclnt
+376 NOPROTO BSD { int eaccess(char *path, int flags); }
377 UNIMPL BSD afs_syscall
-378 STD BSD { int nmount(struct iovec *iovp, unsigned int iovcnt, \
+378 NOPROTO BSD { int nmount(struct iovec *iovp, unsigned int iovcnt, \
int flags); }
-379 STD BSD { int kse_exit(void); }
-380 STD BSD { int kse_wakeup(void); }
-381 STD BSD { int kse_new(struct kse_mailbox * mbx, \
+379 NOPROTO BSD { int kse_exit(void); }
+380 NOPROTO BSD { int kse_wakeup(void); }
+381 NOPROTO BSD { int kse_new(struct kse_mailbox * mbx, \
int new_grp_flag); }
-382 STD BSD { int thread_wakeup(struct thread_mailbox *tmbx); }
-383 STD BSD { int kse_yield(void); }
+382 NOPROTO BSD { int thread_wakeup(struct thread_mailbox *tmbx); }
+383 NOPROTO BSD { int kse_yield(void); }
384 UNIMPL BSD __mac_get_proc
385 UNIMPL BSD __mac_set_proc
386 UNIMPL BSD __mac_get_fd
387 UNIMPL BSD __mac_get_file
388 UNIMPL BSD __mac_set_fd
389 UNIMPL BSD __mac_set_file
+390 NOPROTO BSD { int kenv(int what, const char *name, char *value, \
+ int len); }
+391 NOPROTO BSD { int lchflags(const char *path, int flags); }
+392 NOPROTO BSD { int uuidgen(struct uuid *store, int count); }
diff --git a/sys/compat/freebsd32/freebsd32.h b/sys/compat/freebsd32/freebsd32.h
new file mode 100644
index 000000000000..943b24c61ed3
--- /dev/null
+++ b/sys/compat/freebsd32/freebsd32.h
@@ -0,0 +1,103 @@
+/*-
+ * Copyright (c) 2001 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _IA64_IA32_IA32_H_
+#define _IA64_IA32_IA32_H_
+
+#define PTRIN(v) (void *)(uintptr_t) (v)
+#define PTROUT(v) (u_int32_t)(uintptr_t) (v)
+
+#define CP(src,dst,fld) do { (dst).fld = (src).fld; } while (0)
+#define PTRIN_CP(src,dst,fld) \
+ do { (dst).fld = PTRIN((src).fld); } while (0)
+#define PTROUT_CP(src,dst,fld) \
+ do { (dst).fld = PTROUT((src).fld); } while (0)
+
+struct timeval32 {
+ int32_t tv_sec;
+ int32_t tv_usec;
+};
+#define TV_CP(src,dst,fld) do { \
+ CP((src).fld,(dst).fld,tv_sec); \
+ CP((src).fld,(dst).fld,tv_usec); \
+} while (0);
+
+struct timespec32 {
+ u_int32_t tv_sec;
+ u_int32_t tv_nsec;
+};
+#define TS_CP(src,dst,fld) do { \
+ CP((src).fld,(dst).fld,tv_sec); \
+ CP((src).fld,(dst).fld,tv_nsec); \
+} while (0);
+
+struct rusage32 {
+ struct timeval32 ru_utime;
+ struct timeval32 ru_stime;
+ int32_t ru_maxrss;
+ int32_t ru_ixrss;
+ int32_t ru_idrss;
+ int32_t ru_isrss;
+ int32_t ru_minflt;
+ int32_t ru_majflt;
+ int32_t ru_nswap;
+ int32_t ru_inblock;
+ int32_t ru_oublock;
+ int32_t ru_msgsnd;
+ int32_t ru_msgrcv;
+ int32_t ru_nsignals;
+ int32_t ru_nvcsw;
+ int32_t ru_nivcsw;
+};
+
+struct statfs32 {
+ int32_t f_spare2;
+ int32_t f_bsize;
+ int32_t f_iosize;
+ int32_t f_blocks;
+ int32_t f_bfree;
+ int32_t f_bavail;
+ int32_t f_files;
+ int32_t f_ffree;
+ fsid_t f_fsid;
+ uid_t f_owner;
+ int32_t f_type;
+ int32_t f_flags;
+ int32_t f_syncwrites;
+ int32_t f_asyncwrites;
+ char f_fstypename[MFSNAMELEN];
+ char f_mntonname[MNAMELEN];
+ int32_t f_syncreads;
+ int32_t f_asyncreads;
+ int16_t f_spares1;
+ char f_mntfromname[MNAMELEN];
+ int16_t f_spares2;
+ int32_t f_spare[2];
+};
+
+#endif /* !_IA64_IA32_IA32_H_ */
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
new file mode 100644
index 000000000000..8b28bcee0a52
--- /dev/null
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -0,0 +1,1339 @@
+/*-
+ * Copyright (c) 2002 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/dkstat.h>
+#include <sys/exec.h>
+#include <sys/fcntl.h>
+#include <sys/filedesc.h>
+#include <sys/imgact.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/file.h> /* Must come after sys/malloc.h */
+#include <sys/mman.h>
+#include <sys/module.h>
+#include <sys/mount.h>
+#include <sys/mutex.h>
+#include <sys/namei.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/reboot.h>
+#include <sys/resource.h>
+#include <sys/resourcevar.h>
+#include <sys/selinfo.h>
+#include <sys/pipe.h> /* Must come after sys/selinfo.h */
+#include <sys/signal.h>
+#include <sys/signalvar.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/sysent.h>
+#include <sys/sysproto.h>
+#include <sys/systm.h>
+#include <sys/unistd.h>
+#include <sys/user.h>
+#include <sys/utsname.h>
+#include <sys/vnode.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_extern.h>
+
+#include <ia64/ia32/ia32_util.h>
+#include <ia64/ia32/ia32.h>
+#include <ia64/ia32/ia32_proto.h>
+
+static const char ia32_emul_path[] = "/compat/ia32";
+/*
+ * [ taken from the linux emulator ]
+ * Search an alternate path before passing pathname arguments on
+ * to system calls. Useful for keeping a separate 'emulation tree'.
+ *
+ * If cflag is set, we check if an attempt can be made to create
+ * the named file, i.e. we check if the directory it should
+ * be in exists.
+ */
+int
+ia32_emul_find(td, sgp, prefix, path, pbuf, cflag)
+ struct thread *td;
+ caddr_t *sgp; /* Pointer to stackgap memory */
+ const char *prefix;
+ char *path;
+ char **pbuf;
+ int cflag;
+{
+ int error;
+ size_t len, sz;
+ char *buf, *cp, *ptr;
+ struct ucred *ucred;
+ struct nameidata nd;
+ struct nameidata ndroot;
+ struct vattr vat;
+ struct vattr vatroot;
+
+ buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
+ *pbuf = path;
+
+ for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++)
+ continue;
+
+ sz = MAXPATHLEN - (ptr - buf);
+
+ /*
+ * If sgp is not given then the path is already in kernel space
+ */
+ if (sgp == NULL)
+ error = copystr(path, ptr, sz, &len);
+ else
+ error = copyinstr(path, ptr, sz, &len);
+
+ if (error) {
+ free(buf, M_TEMP);
+ return error;
+ }
+
+ if (*ptr != '/') {
+ free(buf, M_TEMP);
+ return EINVAL;
+ }
+
+ /*
+ * We know that there is a / somewhere in this pathname.
+ * Search backwards for it, to find the file's parent dir
+ * to see if it exists in the alternate tree. If it does,
+ * and we want to create a file (cflag is set). We don't
+ * need to worry about the root comparison in this case.
+ */
+
+ if (cflag) {
+ for (cp = &ptr[len] - 1; *cp != '/'; cp--)
+ ;
+ *cp = '\0';
+
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
+
+ if ((error = namei(&nd)) != 0) {
+ free(buf, M_TEMP);
+ return error;
+ }
+
+ *cp = '/';
+ } else {
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
+
+ if ((error = namei(&nd)) != 0) {
+ free(buf, M_TEMP);
+ return error;
+ }
+
+ /*
+ * We now compare the vnode of the ia32_root to the one
+ * vnode asked. If they resolve to be the same, then we
+ * ignore the match so that the real root gets used.
+ * This avoids the problem of traversing "../.." to find the
+ * root directory and never finding it, because "/" resolves
+ * to the emulation root directory. This is expensive :-(
+ */
+ NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, ia32_emul_path,
+ td);
+
+ if ((error = namei(&ndroot)) != 0) {
+ /* Cannot happen! */
+ free(buf, M_TEMP);
+ vrele(nd.ni_vp);
+ return error;
+ }
+
+ ucred = td->td_ucred;
+ if ((error = VOP_GETATTR(nd.ni_vp, &vat, ucred, td)) != 0) {
+ goto bad;
+ }
+
+ if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, ucred,
+ td)) != 0) {
+ goto bad;
+ }
+
+ if (vat.va_fsid == vatroot.va_fsid &&
+ vat.va_fileid == vatroot.va_fileid) {
+ error = ENOENT;
+ goto bad;
+ }
+
+ }
+ if (sgp == NULL)
+ *pbuf = buf;
+ else {
+ sz = &ptr[len] - buf;
+ *pbuf = stackgap_alloc(sgp, sz + 1);
+ error = copyout(buf, *pbuf, sz);
+ free(buf, M_TEMP);
+ }
+
+ vrele(nd.ni_vp);
+ if (!cflag)
+ vrele(ndroot.ni_vp);
+
+ return error;
+
+bad:
+ vrele(ndroot.ni_vp);
+ vrele(nd.ni_vp);
+ free(buf, M_TEMP);
+ return error;
+}
+
+int
+ia32_open(struct thread *td, struct ia32_open_args *uap)
+{
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, uap->path);
+
+ return open(td, (struct open_args *) uap);
+}
+
+int
+ia32_wait4(struct thread *td, struct ia32_wait4_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct rusage32 *rusage32, ru32;
+ struct rusage *rusage = NULL, ru;
+
+ rusage32 = SCARG(uap, rusage);
+ if (rusage32) {
+ sg = stackgap_init();
+ rusage = stackgap_alloc(&sg, sizeof(struct rusage));
+ SCARG(uap, rusage) = (struct rusage32 *)rusage;
+ }
+ error = wait4(td, (struct wait_args *)uap);
+ if (error)
+ return (error);
+ if (rusage32 && (error = copyin(rusage, &ru, sizeof(ru)) == 0)) {
+ TV_CP(ru, ru32, ru_utime);
+ TV_CP(ru, ru32, ru_stime);
+ CP(ru, ru32, ru_maxrss);
+ CP(ru, ru32, ru_ixrss);
+ CP(ru, ru32, ru_idrss);
+ CP(ru, ru32, ru_isrss);
+ CP(ru, ru32, ru_minflt);
+ CP(ru, ru32, ru_majflt);
+ CP(ru, ru32, ru_nswap);
+ CP(ru, ru32, ru_inblock);
+ CP(ru, ru32, ru_oublock);
+ CP(ru, ru32, ru_msgsnd);
+ CP(ru, ru32, ru_msgrcv);
+ CP(ru, ru32, ru_nsignals);
+ CP(ru, ru32, ru_nvcsw);
+ CP(ru, ru32, ru_nivcsw);
+ error = copyout(&ru32, rusage32, sizeof(ru32));
+ }
+ return (error);
+}
+
+static void
+copy_statfs(struct statfs *in, struct statfs32 *out)
+{
+ CP(*in, *out, f_bsize);
+ CP(*in, *out, f_iosize);
+ CP(*in, *out, f_blocks);
+ CP(*in, *out, f_bfree);
+ CP(*in, *out, f_bavail);
+ CP(*in, *out, f_files);
+ CP(*in, *out, f_ffree);
+ CP(*in, *out, f_fsid);
+ CP(*in, *out, f_owner);
+ CP(*in, *out, f_type);
+ CP(*in, *out, f_flags);
+ CP(*in, *out, f_flags);
+ CP(*in, *out, f_syncwrites);
+ CP(*in, *out, f_asyncwrites);
+ bcopy(in->f_fstypename,
+ out->f_fstypename, MFSNAMELEN);
+ bcopy(in->f_mntonname,
+ out->f_mntonname, MNAMELEN);
+ CP(*in, *out, f_syncreads);
+ CP(*in, *out, f_asyncreads);
+ bcopy(in->f_mntfromname,
+ out->f_mntfromname, MNAMELEN);
+}
+
+int
+ia32_getfsstat(struct thread *td, struct ia32_getfsstat_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct statfs32 *sp32, stat32;
+ struct statfs *sp = NULL, stat;
+ int maxcount, count, i;
+
+ sp32 = SCARG(uap, buf);
+ maxcount = SCARG(uap, bufsize) / sizeof(struct statfs32);
+
+ if (sp32) {
+ sg = stackgap_init();
+ sp = stackgap_alloc(&sg, sizeof(struct statfs) * maxcount);
+ SCARG(uap, buf) = (struct statfs32 *)sp;
+ }
+ error = getfsstat(td, (struct getfsstat_args *) uap);
+ if (sp32 && !error) {
+ count = td->td_retval[0];
+ for (i = 0; i < count; i++) {
+ error = copyin(&sp[i], &stat, sizeof(stat));
+ if (error)
+ return (error);
+ copy_statfs(&stat, &stat32);
+ error = copyout(&stat32, &sp32[i], sizeof(stat32));
+ if (error)
+ return (error);
+ }
+ }
+ return (error);
+}
+
+int
+ia32_access(struct thread *td, struct ia32_access_args *uap)
+{
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, uap->path);
+
+ return access(td, (struct access_args *)uap);
+}
+
+int
+ia32_chflags(struct thread *td, struct ia32_chflags_args *uap)
+{
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, uap->path);
+
+ return chflags(td, (struct chflags_args *)uap);
+}
+
+struct sigaltstack32 {
+ u_int32_t ss_sp;
+ u_int32_t ss_size;
+ int ss_flags;
+};
+
+int
+ia32_sigaltstack(struct thread *td, struct ia32_sigaltstack_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct sigaltstack32 *p32, *op32, s32;
+ struct sigaltstack *p = NULL, *op = NULL, s;
+
+ p32 = SCARG(uap, ss);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct sigaltstack));
+ SCARG(uap, ss) = (struct sigaltstack32 *)p;
+ error = copyin(p32, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ PTRIN_CP(s32, s, ss_sp);
+ CP(s32, s, ss_size);
+ CP(s32, s, ss_flags);
+ error = copyout(&s, p, sizeof(s));
+ if (error)
+ return (error);
+ }
+ op32 = SCARG(uap, oss);
+ if (op32) {
+ sg = stackgap_init();
+ op = stackgap_alloc(&sg, sizeof(struct sigaltstack));
+ SCARG(uap, oss) = (struct sigaltstack32 *)op;
+ }
+ error = sigaltstack(td, (struct sigaltstack_args *) uap);
+ if (error)
+ return (error);
+ if (op32) {
+ error = copyin(op, &s, sizeof(s));
+ if (error)
+ return (error);
+ PTROUT_CP(s, s32, ss_sp);
+ CP(s, s32, ss_size);
+ CP(s, s32, ss_flags);
+ error = copyout(&s32, op32, sizeof(s32));
+ }
+ return (error);
+}
+
+int
+ia32_execve(struct thread *td, struct ia32_execve_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct execve_args ap;
+ u_int32_t *p32, arg;
+ char **p;
+ int count;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, SCARG(uap, fname));
+ SCARG(&ap, fname) = SCARG(uap, fname);
+
+ if (SCARG(uap, argv)) {
+ count = 0;
+ p32 = SCARG(uap, argv);
+ do {
+ error = copyin(p32++, &arg, sizeof(arg));
+ if (error)
+ return error;
+ count++;
+ } while (arg != 0);
+ p = stackgap_alloc(&sg, count * sizeof(char *));
+ SCARG(&ap, argv) = p;
+ p32 = SCARG(uap, argv);
+ do {
+ error = copyin(p32++, &arg, sizeof(arg));
+ if (error)
+ return error;
+ *p++ = PTRIN(arg);
+ } while (arg != 0);
+ }
+ if (SCARG(uap, envv)) {
+ count = 0;
+ p32 = SCARG(uap, envv);
+ do {
+ error = copyin(p32++, &arg, sizeof(arg));
+ if (error)
+ return error;
+ count++;
+ } while (arg != 0);
+ p = stackgap_alloc(&sg, count * sizeof(char *));
+ SCARG(&ap, envv) = p;
+ p32 = SCARG(uap, envv);
+ do {
+ error = copyin(p32++, &arg, sizeof(arg));
+ if (error)
+ return error;
+ *p++ = PTRIN(arg);
+ } while (arg != 0);
+ }
+
+ return execve(td, &ap);
+}
+
+static int
+ia32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
+ int prot, int fd, off_t pos)
+{
+ vm_map_t map;
+ vm_map_entry_t entry;
+ int rv;
+
+ map = &td->td_proc->p_vmspace->vm_map;
+ if (fd != -1)
+ prot |= VM_PROT_WRITE;
+
+ if (vm_map_lookup_entry(map, start, &entry)) {
+ if ((entry->protection & prot) != prot) {
+ rv = vm_map_protect(map,
+ trunc_page(start),
+ round_page(end),
+ entry->protection | prot,
+ FALSE);
+ if (rv != KERN_SUCCESS)
+ return (EINVAL);
+ }
+ } else {
+ vm_offset_t addr = trunc_page(start);
+ rv = vm_map_find(map, 0, 0,
+ &addr, PAGE_SIZE, FALSE, prot,
+ VM_PROT_ALL, 0);
+ if (rv != KERN_SUCCESS)
+ return (EINVAL);
+ }
+
+ if (fd != -1) {
+ struct pread_args r;
+ SCARG(&r, fd) = fd;
+ SCARG(&r, buf) = (void *) start;
+ SCARG(&r, nbyte) = end - start;
+ SCARG(&r, offset) = pos;
+ return (pread(td, &r));
+ } else {
+ while (start < end) {
+ subyte((void *) start, 0);
+ start++;
+ }
+ return (0);
+ }
+}
+
+int
+ia32_mmap(struct thread *td, struct ia32_mmap_args *uap)
+{
+ struct mmap_args ap;
+ vm_offset_t addr = (vm_offset_t) SCARG(uap, addr);
+ vm_size_t len = SCARG(uap, len);
+ int prot = SCARG(uap, prot);
+ int flags = SCARG(uap, flags);
+ int fd = SCARG(uap, fd);
+ off_t pos = (SCARG(uap, poslo)
+ | ((off_t)SCARG(uap, poshi) << 32));
+ vm_size_t pageoff;
+ int error;
+
+ /*
+ * Attempt to handle page size hassles.
+ */
+ pageoff = (pos & PAGE_MASK);
+ if (flags & MAP_FIXED) {
+ vm_offset_t start, end;
+ start = addr;
+ end = addr + len;
+
+ if (start != trunc_page(start)) {
+ error = ia32_mmap_partial(td, start, round_page(start),
+ prot, fd, pos);
+ if (fd != -1)
+ pos += round_page(start) - start;
+ start = round_page(start);
+ }
+ if (end != round_page(end)) {
+ vm_offset_t t = trunc_page(end);
+ error = ia32_mmap_partial(td, t, end,
+ prot, fd,
+ pos + t - start);
+ end = trunc_page(end);
+ }
+ if (end > start && fd != -1 && (pos & PAGE_MASK)) {
+ /*
+ * We can't map this region at all. The specified
+ * address doesn't have the same alignment as the file
+ * position. Fake the mapping by simply reading the
+ * entire region into memory. First we need to make
+ * sure the region exists.
+ */
+ vm_map_t map;
+ struct pread_args r;
+ int rv;
+
+ prot |= VM_PROT_WRITE;
+ map = &td->td_proc->p_vmspace->vm_map;
+ rv = vm_map_remove(map, start, end);
+ if (rv != KERN_SUCCESS)
+ return (EINVAL);
+ rv = vm_map_find(map, 0, 0,
+ &start, end - start, FALSE,
+ prot, VM_PROT_ALL, 0);
+ if (rv != KERN_SUCCESS)
+ return (EINVAL);
+ SCARG(&r, fd) = fd;
+ SCARG(&r, buf) = (void *) start;
+ SCARG(&r, nbyte) = end - start;
+ SCARG(&r, offset) = pos;
+ error = pread(td, &r);
+ if (error)
+ return (error);
+
+ td->td_retval[0] = addr;
+ return (0);
+ }
+ if (end == start) {
+ /*
+ * After dealing with the ragged ends, there
+ * might be none left.
+ */
+ td->td_retval[0] = addr;
+ return (0);
+ }
+ addr = start;
+ len = end - start;
+ }
+
+ SCARG(&ap, addr) = (void *) addr;
+ SCARG(&ap, len) = len;
+ SCARG(&ap, prot) = prot;
+ SCARG(&ap, flags) = flags;
+ SCARG(&ap, fd) = fd;
+ SCARG(&ap, pos) = pos;
+
+ return (mmap(td, &ap));
+}
+
+struct itimerval32 {
+ struct timeval32 it_interval;
+ struct timeval32 it_value;
+};
+
+int
+ia32_setitimer(struct thread *td, struct ia32_setitimer_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct itimerval32 *p32, *op32, s32;
+ struct itimerval *p = NULL, *op = NULL, s;
+
+ p32 = SCARG(uap, itv);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct itimerval));
+ SCARG(uap, itv) = (struct itimerval32 *)p;
+ error = copyin(p32, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ TV_CP(s32, s, it_interval);
+ TV_CP(s32, s, it_value);
+ error = copyout(&s, p, sizeof(s));
+ if (error)
+ return (error);
+ }
+ op32 = SCARG(uap, oitv);
+ if (op32) {
+ sg = stackgap_init();
+ op = stackgap_alloc(&sg, sizeof(struct itimerval));
+ SCARG(uap, oitv) = (struct itimerval32 *)op;
+ }
+ error = setitimer(td, (struct setitimer_args *) uap);
+ if (error)
+ return (error);
+ if (op32) {
+ error = copyin(op, &s, sizeof(s));
+ if (error)
+ return (error);
+ TV_CP(s, s32, it_interval);
+ TV_CP(s, s32, it_value);
+ error = copyout(&s32, op32, sizeof(s32));
+ }
+ return (error);
+}
+
+int
+ia32_select(struct thread *td, struct ia32_select_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct timeval32 *p32, s32;
+ struct timeval *p = NULL, s;
+
+ p32 = SCARG(uap, tv);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct timeval));
+ SCARG(uap, tv) = (struct timeval32 *)p;
+ error = copyin(p32, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ CP(s32, s, tv_sec);
+ CP(s32, s, tv_usec);
+ error = copyout(&s, p, sizeof(s));
+ if (error)
+ return (error);
+ }
+ /*
+ * XXX big-endian needs to convert the fd_sets too.
+ */
+ return (select(td, (struct select_args *) uap));
+}
+
+int
+ia32_gettimeofday(struct thread *td, struct ia32_gettimeofday_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct timeval32 *p32, s32;
+ struct timeval *p = NULL, s;
+
+ p32 = SCARG(uap, tp);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct timeval));
+ SCARG(uap, tp) = (struct timeval32 *)p;
+ }
+ error = gettimeofday(td, (struct gettimeofday_args *) uap);
+ if (error)
+ return (error);
+ if (p32) {
+ error = copyin(p, &s, sizeof(s));
+ if (error)
+ return (error);
+ CP(s, s32, tv_sec);
+ CP(s, s32, tv_usec);
+ error = copyout(&s32, p32, sizeof(s32));
+ if (error)
+ return (error);
+ }
+ return (error);
+}
+
+int
+ia32_getrusage(struct thread *td, struct ia32_getrusage_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct rusage32 *p32, s32;
+ struct rusage *p = NULL, s;
+
+ p32 = SCARG(uap, rusage);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct rusage));
+ SCARG(uap, rusage) = (struct rusage32 *)p;
+ }
+ error = getrusage(td, (struct getrusage_args *) uap);
+ if (error)
+ return (error);
+ if (p32) {
+ error = copyin(p, &s, sizeof(s));
+ if (error)
+ return (error);
+ TV_CP(s, s32, ru_utime);
+ TV_CP(s, s32, ru_stime);
+ CP(s, s32, ru_maxrss);
+ CP(s, s32, ru_ixrss);
+ CP(s, s32, ru_idrss);
+ CP(s, s32, ru_isrss);
+ CP(s, s32, ru_minflt);
+ CP(s, s32, ru_majflt);
+ CP(s, s32, ru_nswap);
+ CP(s, s32, ru_inblock);
+ CP(s, s32, ru_oublock);
+ CP(s, s32, ru_msgsnd);
+ CP(s, s32, ru_msgrcv);
+ CP(s, s32, ru_nsignals);
+ CP(s, s32, ru_nvcsw);
+ CP(s, s32, ru_nivcsw);
+ error = copyout(&s32, p32, sizeof(s32));
+ }
+ return (error);
+}
+
+struct iovec32 {
+ u_int32_t iov_base;
+ int iov_len;
+};
+#define STACKGAPLEN 400
+
+int
+ia32_readv(struct thread *td, struct ia32_readv_args *uap)
+{
+ int error, osize, nsize, i;
+ caddr_t sg;
+ struct readv_args /* {
+ syscallarg(int) fd;
+ syscallarg(struct iovec *) iovp;
+ syscallarg(u_int) iovcnt;
+ } */ a;
+ struct iovec32 *oio;
+ struct iovec *nio;
+
+ sg = stackgap_init();
+
+ if (SCARG(uap, iovcnt) > (STACKGAPLEN / sizeof (struct iovec)))
+ return (EINVAL);
+
+ osize = SCARG(uap, iovcnt) * sizeof (struct iovec32);
+ nsize = SCARG(uap, iovcnt) * sizeof (struct iovec);
+
+ oio = malloc(osize, M_TEMP, M_WAITOK);
+ nio = malloc(nsize, M_TEMP, M_WAITOK);
+
+ error = 0;
+ if ((error = copyin(SCARG(uap, iovp), oio, osize)))
+ goto punt;
+ for (i = 0; i < SCARG(uap, iovcnt); i++) {
+ nio[i].iov_base = PTRIN(oio[i].iov_base);
+ nio[i].iov_len = oio[i].iov_len;
+ }
+
+ SCARG(&a, fd) = SCARG(uap, fd);
+ SCARG(&a, iovp) = stackgap_alloc(&sg, nsize);
+ SCARG(&a, iovcnt) = SCARG(uap, iovcnt);
+
+ if ((error = copyout(nio, (caddr_t)SCARG(&a, iovp), nsize)))
+ goto punt;
+ error = readv(td, &a);
+
+punt:
+ free(oio, M_TEMP);
+ free(nio, M_TEMP);
+ return (error);
+}
+
+int
+ia32_writev(struct thread *td, struct ia32_writev_args *uap)
+{
+ int error, i, nsize, osize;
+ caddr_t sg;
+ struct writev_args /* {
+ syscallarg(int) fd;
+ syscallarg(struct iovec *) iovp;
+ syscallarg(u_int) iovcnt;
+ } */ a;
+ struct iovec32 *oio;
+ struct iovec *nio;
+
+ sg = stackgap_init();
+
+ if (SCARG(uap, iovcnt) > (STACKGAPLEN / sizeof (struct iovec)))
+ return (EINVAL);
+
+ osize = SCARG(uap, iovcnt) * sizeof (struct iovec32);
+ nsize = SCARG(uap, iovcnt) * sizeof (struct iovec);
+
+ oio = malloc(osize, M_TEMP, M_WAITOK);
+ nio = malloc(nsize, M_TEMP, M_WAITOK);
+
+ error = 0;
+ if ((error = copyin(SCARG(uap, iovp), oio, osize)))
+ goto punt;
+ for (i = 0; i < SCARG(uap, iovcnt); i++) {
+ nio[i].iov_base = PTRIN(oio[i].iov_base);
+ nio[i].iov_len = oio[i].iov_len;
+ }
+
+ SCARG(&a, fd) = SCARG(uap, fd);
+ SCARG(&a, iovp) = stackgap_alloc(&sg, nsize);
+ SCARG(&a, iovcnt) = SCARG(uap, iovcnt);
+
+ if ((error = copyout(nio, (caddr_t)SCARG(&a, iovp), nsize)))
+ goto punt;
+ error = writev(td, &a);
+
+punt:
+ free(oio, M_TEMP);
+ free(nio, M_TEMP);
+ return (error);
+}
+
+int
+ia32_settimeofday(struct thread *td, struct ia32_settimeofday_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct timeval32 *p32, s32;
+ struct timeval *p = NULL, s;
+
+ p32 = SCARG(uap, tv);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct timeval));
+ SCARG(uap, tv) = (struct timeval32 *)p;
+ error = copyin(p32, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ CP(s32, s, tv_sec);
+ CP(s32, s, tv_usec);
+ error = copyout(&s, p, sizeof(s));
+ if (error)
+ return (error);
+ }
+ return (settimeofday(td, (struct settimeofday_args *) uap));
+}
+
+int
+ia32_utimes(struct thread *td, struct ia32_utimes_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct timeval32 *p32, s32[2];
+ struct timeval *p = NULL, s[2];
+
+ p32 = SCARG(uap, tptr);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, 2*sizeof(struct timeval));
+ SCARG(uap, tptr) = (struct timeval32 *)p;
+ error = copyin(p32, s32, sizeof(s32));
+ if (error)
+ return (error);
+ CP(s32[0], s[0], tv_sec);
+ CP(s32[0], s[0], tv_usec);
+ CP(s32[1], s[1], tv_sec);
+ CP(s32[1], s[1], tv_usec);
+ error = copyout(s, p, sizeof(s));
+ if (error)
+ return (error);
+ }
+ return (utimes(td, (struct utimes_args *) uap));
+}
+
+int
+ia32_adjtime(struct thread *td, struct ia32_adjtime_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct timeval32 *p32, *op32, s32;
+ struct timeval *p = NULL, *op = NULL, s;
+
+ p32 = SCARG(uap, delta);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct timeval));
+ SCARG(uap, delta) = (struct timeval32 *)p;
+ error = copyin(p32, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ CP(s32, s, tv_sec);
+ CP(s32, s, tv_usec);
+ error = copyout(&s, p, sizeof(s));
+ if (error)
+ return (error);
+ }
+ op32 = SCARG(uap, olddelta);
+ if (op32) {
+ sg = stackgap_init();
+ op = stackgap_alloc(&sg, sizeof(struct timeval));
+ SCARG(uap, olddelta) = (struct timeval32 *)op;
+ }
+ error = utimes(td, (struct utimes_args *) uap);
+ if (error)
+ return error;
+ if (op32) {
+ error = copyin(op, &s, sizeof(s));
+ if (error)
+ return (error);
+ CP(s, s32, tv_sec);
+ CP(s, s32, tv_usec);
+ error = copyout(&s32, op32, sizeof(s32));
+ }
+ return (error);
+}
+
+int
+ia32_statfs(struct thread *td, struct ia32_statfs_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct statfs32 *p32, s32;
+ struct statfs *p = NULL, s;
+
+ p32 = SCARG(uap, buf);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct statfs));
+ SCARG(uap, buf) = (struct statfs32 *)p;
+ }
+ error = statfs(td, (struct statfs_args *) uap);
+ if (error)
+ return (error);
+ if (p32) {
+ error = copyin(p, &s, sizeof(s));
+ if (error)
+ return (error);
+ copy_statfs(&s, &s32);
+ error = copyout(&s32, p32, sizeof(s32));
+ }
+ return (error);
+}
+
+int
+ia32_fstatfs(struct thread *td, struct ia32_fstatfs_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct statfs32 *p32, s32;
+ struct statfs *p = NULL, s;
+
+ p32 = SCARG(uap, buf);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct statfs));
+ SCARG(uap, buf) = (struct statfs32 *)p;
+ }
+ error = fstatfs(td, (struct fstatfs_args *) uap);
+ if (error)
+ return (error);
+ if (p32) {
+ error = copyin(p, &s, sizeof(s));
+ if (error)
+ return (error);
+ copy_statfs(&s, &s32);
+ error = copyout(&s32, p32, sizeof(s32));
+ }
+ return (error);
+}
+
+int
+ia32_semsys(struct thread *td, struct ia32_semsys_args *uap)
+{
+ /*
+ * Vector through to semsys if it is loaded.
+ */
+ return sysent[169].sy_call(td, uap);
+}
+
+int
+ia32_msgsys(struct thread *td, struct ia32_msgsys_args *uap)
+{
+ /*
+ * Vector through to msgsys if it is loaded.
+ */
+ return sysent[170].sy_call(td, uap);
+}
+
+int
+ia32_shmsys(struct thread *td, struct ia32_shmsys_args *uap)
+{
+ /*
+ * Vector through to shmsys if it is loaded.
+ */
+ return sysent[171].sy_call(td, uap);
+}
+
+int
+ia32_pread(struct thread *td, struct ia32_pread_args *uap)
+{
+ struct pread_args ap;
+
+ SCARG(&ap, fd) = SCARG(uap, fd);
+ SCARG(&ap, buf) = SCARG(uap, buf);
+ SCARG(&ap, nbyte) = SCARG(uap, nbyte);
+ SCARG(&ap, offset) = (SCARG(uap, offsetlo)
+ | ((off_t)SCARG(uap, offsethi) << 32));
+ return (pread(td, &ap));
+}
+
+int
+ia32_pwrite(struct thread *td, struct ia32_pwrite_args *uap)
+{
+ struct pwrite_args ap;
+
+ SCARG(&ap, fd) = SCARG(uap, fd);
+ SCARG(&ap, buf) = SCARG(uap, buf);
+ SCARG(&ap, nbyte) = SCARG(uap, nbyte);
+ SCARG(&ap, offset) = (SCARG(uap, offsetlo)
+ | ((off_t)SCARG(uap, offsethi) << 32));
+ return (pwrite(td, &ap));
+}
+
+int
+ia32_lseek(struct thread *td, struct ia32_lseek_args *uap)
+{
+ int error;
+ struct lseek_args ap;
+ off_t pos;
+
+ SCARG(&ap, fd) = SCARG(uap, fd);
+ SCARG(&ap, offset) = (SCARG(uap, offsetlo)
+ | ((off_t)SCARG(uap, offsethi) << 32));
+ SCARG(&ap, whence) = SCARG(uap, whence);
+ error = lseek(td, &ap);
+ /* Expand the quad return into two parts for eax and edx */
+ pos = *(off_t *)(td->td_retval);
+ td->td_retval[0] = pos & 0xffffffff; /* %eax */
+ td->td_retval[1] = pos >> 32; /* %edx */
+ return error;
+}
+
+int
+ia32_truncate(struct thread *td, struct ia32_truncate_args *uap)
+{
+ struct truncate_args ap;
+
+ SCARG(&ap, path) = SCARG(uap, path);
+ SCARG(&ap, length) = (SCARG(uap, lengthlo)
+ | ((off_t)SCARG(uap, lengthhi) << 32));
+ return (truncate(td, &ap));
+}
+
+int
+ia32_ftruncate(struct thread *td, struct ia32_ftruncate_args *uap)
+{
+ struct ftruncate_args ap;
+
+ SCARG(&ap, fd) = SCARG(uap, fd);
+ SCARG(&ap, length) = (SCARG(uap, lengthlo)
+ | ((off_t)SCARG(uap, lengthhi) << 32));
+ return (ftruncate(td, &ap));
+}
+
+int
+ia32_sendfile(struct thread *td, struct ia32_sendfile_args *uap)
+{
+ struct sendfile_args ap;
+
+ SCARG(&ap, fd) = SCARG(uap, fd);
+ SCARG(&ap, s) = SCARG(uap, s);
+ SCARG(&ap, offset) = (SCARG(uap, offsetlo)
+ | ((off_t)SCARG(uap, offsethi) << 32));
+ SCARG(&ap, nbytes) = SCARG(uap, nbytes); /* XXX check */
+ SCARG(&ap, hdtr) = SCARG(uap, hdtr); /* XXX check */
+ SCARG(&ap, sbytes) = SCARG(uap, sbytes); /* XXX FIXME!! */
+ SCARG(&ap, flags) = SCARG(uap, flags);
+ return (sendfile(td, &ap));
+}
+
+struct stat32 {
+ udev_t st_dev;
+ ino_t st_ino;
+ mode_t st_mode;
+ nlink_t st_nlink;
+ uid_t st_uid;
+ gid_t st_gid;
+ udev_t st_rdev;
+ struct timespec32 st_atimespec;
+ struct timespec32 st_mtimespec;
+ struct timespec32 st_ctimespec;
+ off_t st_size;
+ int64_t st_blocks;
+ u_int32_t st_blksize;
+ u_int32_t st_flags;
+ u_int32_t st_gen;
+};
+
+static void
+copy_stat( struct stat *in, struct stat32 *out)
+{
+ CP(*in, *out, st_dev);
+ CP(*in, *out, st_ino);
+ CP(*in, *out, st_mode);
+ CP(*in, *out, st_nlink);
+ CP(*in, *out, st_uid);
+ CP(*in, *out, st_gid);
+ CP(*in, *out, st_rdev);
+ TS_CP(*in, *out, st_atimespec);
+ TS_CP(*in, *out, st_mtimespec);
+ TS_CP(*in, *out, st_ctimespec);
+ CP(*in, *out, st_size);
+ CP(*in, *out, st_blocks);
+ CP(*in, *out, st_blksize);
+ CP(*in, *out, st_flags);
+ CP(*in, *out, st_gen);
+}
+
+int
+ia32_stat(struct thread *td, struct ia32_stat_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct stat32 *p32, s32;
+ struct stat *p = NULL, s;
+
+ p32 = SCARG(uap, ub);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct stat));
+ SCARG(uap, ub) = (struct stat32 *)p;
+ }
+ error = stat(td, (struct stat_args *) uap);
+ if (error)
+ return (error);
+ if (p32) {
+ error = copyin(p, &s, sizeof(s));
+ if (error)
+ return (error);
+ copy_stat(&s, &s32);
+ error = copyout(&s32, p32, sizeof(s32));
+ }
+ return (error);
+}
+
+int
+ia32_fstat(struct thread *td, struct ia32_fstat_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct stat32 *p32, s32;
+ struct stat *p = NULL, s;
+
+ p32 = SCARG(uap, ub);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct stat));
+ SCARG(uap, ub) = (struct stat32 *)p;
+ }
+ error = fstat(td, (struct fstat_args *) uap);
+ if (error)
+ return (error);
+ if (p32) {
+ error = copyin(p, &s, sizeof(s));
+ if (error)
+ return (error);
+ copy_stat(&s, &s32);
+ error = copyout(&s32, p32, sizeof(s32));
+ }
+ return (error);
+}
+
+int
+ia32_lstat(struct thread *td, struct ia32_lstat_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct stat32 *p32, s32;
+ struct stat *p = NULL, s;
+
+ p32 = SCARG(uap, ub);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct stat));
+ SCARG(uap, ub) = (struct stat32 *)p;
+ }
+ error = lstat(td, (struct lstat_args *) uap);
+ if (error)
+ return (error);
+ if (p32) {
+ error = copyin(p, &s, sizeof(s));
+ if (error)
+ return (error);
+ copy_stat(&s, &s32);
+ error = copyout(&s32, p32, sizeof(s32));
+ }
+ return (error);
+}
+
+/*
+ * MPSAFE
+ */
+int
+ia32_sysctl(struct thread *td, struct ia32_sysctl_args *uap)
+{
+ int error, name[CTL_MAXNAME];
+ size_t j, oldlen;
+
+ if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
+ return (EINVAL);
+
+ error = copyin(uap->name, &name, uap->namelen * sizeof(int));
+ if (error)
+ return (error);
+
+ mtx_lock(&Giant);
+
+ if (uap->oldlenp)
+ oldlen = fuword32(uap->oldlenp);
+ else
+ oldlen = 0;
+ error = userland_sysctl(td, name, uap->namelen,
+ uap->old, &oldlen, 1,
+ uap->new, uap->newlen, &j);
+ if (error && error != ENOMEM)
+ goto done2;
+ if (uap->oldlenp) {
+ suword32(uap->oldlenp, j);
+ }
+done2:
+ mtx_unlock(&Giant);
+ return (error);
+}
+
+struct sigaction32 {
+ u_int32_t sa_u;
+ int sa_flags;
+ sigset_t sa_mask;
+};
+
+int
+ia32_sigaction(struct thread *td, struct ia32_sigaction_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct sigaction32 *p32, *op32, s32;
+ struct sigaction *p = NULL, *op = NULL, s;
+
+ p32 = SCARG(uap, act);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct sigaction));
+ SCARG(uap, act) = (struct sigaction32 *)p;
+ error = copyin(p32, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ s.sa_handler = PTRIN(s32.sa_u);
+ CP(s32, s, sa_flags);
+ CP(s32, s, sa_mask);
+ error = copyout(&s, p, sizeof(s));
+ if (error)
+ return (error);
+ }
+ op32 = SCARG(uap, oact);
+ if (op32) {
+ sg = stackgap_init();
+ op = stackgap_alloc(&sg, sizeof(struct sigaction));
+ SCARG(uap, oact) = (struct sigaction32 *)op;
+ }
+ error = sigaction(td, (struct sigaction_args *) uap);
+ if (error)
+ return (error);
+ if (op32) {
+ error = copyin(op, &s, sizeof(s));
+ if (error)
+ return (error);
+ s32.sa_u = PTROUT(s.sa_handler);
+ CP(s, s32, sa_flags);
+ CP(s, s32, sa_mask);
+ error = copyout(&s32, op32, sizeof(s32));
+ }
+ return (error);
+}
+
+#if 0
+
+int
+ia32_xxx(struct thread *td, struct ia32_xxx_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct yyy32 *p32, s32;
+ struct yyy *p = NULL, s;
+
+ p32 = SCARG(uap, zzz);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct yyy));
+ SCARG(uap, zzz) = (struct yyy32 *)p;
+ error = copyin(p32, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ /* translate in */
+ error = copyout(&s, p, sizeof(s));
+ if (error)
+ return (error);
+ }
+ error = xxx(td, (struct xxx_args *) uap);
+ if (error)
+ return (error);
+ if (p32) {
+ error = copyin(p, &s, sizeof(s));
+ if (error)
+ return (error);
+ /* translate out */
+ error = copyout(&s32, p32, sizeof(s32));
+ }
+ return (error);
+}
+
+#endif
diff --git a/sys/compat/freebsd32/freebsd32_util.h b/sys/compat/freebsd32/freebsd32_util.h
new file mode 100644
index 000000000000..b9e0a7c4d98a
--- /dev/null
+++ b/sys/compat/freebsd32/freebsd32_util.h
@@ -0,0 +1,94 @@
+/*-
+ * Copyright (c) 1998-1999 Andrew Gallatin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+
+
+#include <sys/exec.h>
+#include <sys/sysent.h>
+#include <sys/cdefs.h>
+
+
+#ifndef SCARG
+#define SCARG(p, x) (p)->x
+#endif
+
+struct ia32_ps_strings {
+ u_int32_t ps_argvstr; /* first of 0 or more argument strings */
+ int ps_nargvstr; /* the number of argument strings */
+ u_int32_t ps_envstr; /* first of 0 or more environment strings */
+ int ps_nenvstr; /* the number of environment strings */
+};
+
+#define IA32_USRSTACK (4L*1024*1024*1024 - PAGE_SIZE)
+#define IA32_PS_STRINGS (IA32_USRSTACK - sizeof(struct ia32_ps_strings))
+
+static __inline caddr_t stackgap_init(void);
+static __inline void *stackgap_alloc(caddr_t *, size_t);
+
+static __inline caddr_t
+stackgap_init()
+{
+#define szsigcode (*(curproc->p_sysent->sv_szsigcode))
+ return (caddr_t)(((caddr_t)IA32_PS_STRINGS) - szsigcode - SPARE_USRSPACE);
+#undef szsigcode
+}
+
+static __inline void *
+stackgap_alloc(sgp, sz)
+ caddr_t *sgp;
+ size_t sz;
+{
+ void *p;
+
+ p = (void *) *sgp;
+ *sgp += ALIGN(sz);
+ return p;
+}
+
+
+extern const char ia32_emul_path[];
+int ia32_emul_find(struct thread *, caddr_t *, const char *, char *,
+ char **, int);
+
+#define CHECKALT(p, sgp, path, i) \
+ do { \
+ int _error; \
+ \
+ _error = ia32_emul_find(p, sgp, ia32_emul_path, path, \
+ &path, i); \
+ if (_error == EFAULT) \
+ return (_error); \
+ } while (0)
+
+#define CHECKALTEXIST(p, sgp, path) CHECKALT((p), (sgp), (path), 0)
+#define CHECKALTCREAT(p, sgp, path) CHECKALT((p), (sgp), (path), 1)
diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master
index 347196a3da99..6de1c57b3665 100644
--- a/sys/compat/freebsd32/syscalls.master
+++ b/sys/compat/freebsd32/syscalls.master
@@ -36,6 +36,9 @@
#include <sys/param.h>
#include <sys/sysent.h>
#include <sys/sysproto.h>
+#include <sys/mount.h>
+#include <ia64/ia32/ia32.h>
+#include <ia64/ia32/ia32_proto.h>
; Reserved/unimplemented system calls in the range 0-150 inclusive
; are reserved for use in future Berkeley releases.
@@ -43,200 +46,189 @@
; redistributions should be placed in the reserved range at the end
; of the current calls.
-0 STD NOHIDE { int nosys(void); } syscall nosys_args int
-1 MSTD NOHIDE { void sys_exit(int rval); } exit sys_exit_args void
-2 MSTD POSIX { int fork(void); }
-3 MSTD POSIX { ssize_t read(int fd, void *buf, size_t nbyte); }
-4 MSTD POSIX { ssize_t write(int fd, const void *buf, size_t nbyte); }
-5 STD POSIX { int open(char *path, int flags, int mode); }
+0 MNOPROTO NOHIDE { int nosys(void); } syscall nosys_args int
+1 MNOPROTO NOHIDE { void sys_exit(int rval); } exit sys_exit_args void
+2 MNOPROTO POSIX { int fork(void); }
+3 MNOPROTO POSIX { ssize_t read(int fd, void *buf, size_t nbyte); }
+4 MNOPROTO POSIX { ssize_t write(int fd, const void *buf, size_t nbyte); }
+5 STD POSIX { int ia32_open(char *path, int flags, int mode); }
; XXX should be { int open(const char *path, int flags, ...); }
; but we're not ready for `const' or varargs.
; XXX man page says `mode_t mode'.
-6 MSTD POSIX { int close(int fd); }
-7 MSTD BSD { int wait4(int pid, int *status, int options, \
- struct rusage *rusage); } wait4 wait_args int
-8 COMPAT BSD { int creat(char *path, int mode); }
-9 STD POSIX { int link(char *path, char *link); }
-10 STD POSIX { int unlink(char *path); }
+6 MNOPROTO POSIX { int close(int fd); }
+7 MSTD BSD { int ia32_wait4(int pid, int *status, int options, \
+ struct rusage32 *rusage); }
+8 OBSOL BSD old creat
+9 NOPROTO POSIX { int link(char *path, char *link); }
+10 NOPROTO POSIX { int unlink(char *path); }
11 OBSOL NOHIDE execv
-12 STD POSIX { int chdir(char *path); }
-13 STD BSD { int fchdir(int fd); }
-14 STD POSIX { int mknod(char *path, int mode, int dev); }
-15 STD POSIX { int chmod(char *path, int mode); }
-16 STD POSIX { int chown(char *path, int uid, int gid); }
-17 MSTD BSD { int obreak(char *nsize); } break obreak_args int
-18 STD BSD { int getfsstat(struct statfs *buf, long bufsize, \
- int flags); }
-19 COMPAT POSIX { long lseek(int fd, long offset, int whence); }
-20 MSTD POSIX { pid_t getpid(void); }
-21 STD BSD { int mount(char *type, char *path, int flags, \
+12 NOPROTO POSIX { int chdir(char *path); }
+13 NOPROTO BSD { int fchdir(int fd); }
+14 NOPROTO POSIX { int mknod(char *path, int mode, int dev); }
+15 NOPROTO POSIX { int chmod(char *path, int mode); }
+16 NOPROTO POSIX { int chown(char *path, int uid, int gid); }
+17 MNOPROTO BSD { int obreak(char *nsize); } break obreak_args int
+18 STD BSD { int ia32_getfsstat(struct statfs32 *buf, \
+ long bufsize, int flags); }
+19 OBSOL POSIX olseek
+20 MNOPROTO POSIX { pid_t getpid(void); }
+21 NOPROTO BSD { int mount(char *type, char *path, int flags, \
caddr_t data); }
; XXX `path' should have type `const char *' but we're not ready for that.
-22 STD BSD { int unmount(char *path, int flags); }
-23 MSTD POSIX { int setuid(uid_t uid); }
-24 MSTD POSIX { uid_t getuid(void); }
-25 MSTD POSIX { uid_t geteuid(void); }
-26 STD BSD { int ptrace(int req, pid_t pid, caddr_t addr, \
+22 NOPROTO BSD { int unmount(char *path, int flags); }
+23 MNOPROTO POSIX { int setuid(uid_t uid); }
+24 MNOPROTO POSIX { uid_t getuid(void); }
+25 MNOPROTO POSIX { uid_t geteuid(void); }
+26 NOPROTO BSD { int ptrace(int req, pid_t pid, caddr_t addr, \
int data); }
-27 MSTD BSD { int recvmsg(int s, struct msghdr *msg, int flags); }
-28 MSTD BSD { int sendmsg(int s, caddr_t msg, int flags); }
-29 MSTD BSD { int recvfrom(int s, caddr_t buf, size_t len, \
+27 UNIMPL BSD recvmsg
+28 MNOPROTO BSD { int sendmsg(int s, caddr_t msg, int flags); }
+29 MNOPROTO BSD { int recvfrom(int s, caddr_t buf, size_t len, \
int flags, caddr_t from, int *fromlenaddr); }
-30 MSTD BSD { int accept(int s, caddr_t name, int *anamelen); }
-31 MSTD BSD { int getpeername(int fdes, caddr_t asa, int *alen); }
-32 MSTD BSD { int getsockname(int fdes, caddr_t asa, int *alen); }
-33 STD POSIX { int access(char *path, int flags); }
-34 STD BSD { int chflags(char *path, int flags); }
-35 STD BSD { int fchflags(int fd, int flags); }
-36 STD BSD { int sync(void); }
-37 MSTD POSIX { int kill(int pid, int signum); }
-38 COMPAT POSIX { int stat(char *path, struct ostat *ub); }
-39 MSTD POSIX { pid_t getppid(void); }
-40 COMPAT POSIX { int lstat(char *path, struct ostat *ub); }
-41 STD POSIX { int dup(u_int fd); }
-42 STD POSIX { int pipe(void); }
-43 MSTD POSIX { gid_t getegid(void); }
-44 MSTD BSD { int profil(caddr_t samples, size_t size, \
+30 MNOPROTO BSD { int accept(int s, caddr_t name, int *anamelen); }
+31 MNOPROTO BSD { int getpeername(int fdes, caddr_t asa, int *alen); }
+32 MNOPROTO BSD { int getsockname(int fdes, caddr_t asa, int *alen); }
+33 STD POSIX { int ia32_access(char *path, int flags); }
+34 STD BSD { int ia32_chflags(char *path, int flags); }
+35 NOPROTO BSD { int fchflags(int fd, int flags); }
+36 NOPROTO BSD { int sync(void); }
+37 MNOPROTO POSIX { int kill(int pid, int signum); }
+38 UNIMPL POSIX ostat
+39 MNOPROTO POSIX { pid_t getppid(void); }
+40 UNIMPL POSIX olstat
+41 NOPROTO POSIX { int dup(u_int fd); }
+42 NOPROTO POSIX { int pipe(void); }
+43 MNOPROTO POSIX { gid_t getegid(void); }
+44 MNOPROTO BSD { int profil(caddr_t samples, size_t size, \
size_t offset, u_int scale); }
-45 STD BSD { int ktrace(const char *fname, int ops, int facs, \
+45 NOPROTO BSD { int ktrace(const char *fname, int ops, int facs, \
int pid); }
-46 MCOMPAT POSIX { int sigaction(int signum, struct osigaction *nsa, \
- struct osigaction *osa); }
-47 MSTD POSIX { gid_t getgid(void); }
-48 MCOMPAT POSIX { int sigprocmask(int how, osigset_t mask); }
-; XXX note nonstandard (bogus) calling convention - the libc stub passes
-; us the mask, not a pointer to it, and we return the old mask as the
-; (int) return value.
-49 MSTD BSD { int getlogin(char *namebuf, u_int namelen); }
-50 MSTD BSD { int setlogin(char *namebuf); }
-51 MSTD BSD { int acct(char *path); }
-52 MCOMPAT POSIX { int sigpending(void); }
-53 MSTD BSD { int sigaltstack(stack_t *ss, stack_t *oss); }
-54 MSTD POSIX { int ioctl(int fd, u_long com, caddr_t data); }
-55 MSTD BSD { int reboot(int opt); }
-56 STD POSIX { int revoke(char *path); }
-57 STD POSIX { int symlink(char *path, char *link); }
-58 STD POSIX { int readlink(char *path, char *buf, int count); }
-59 MSTD POSIX { int execve(char *fname, char **argv, char **envv); }
-60 MSTD POSIX { int umask(int newmask); } umask umask_args int
-61 STD BSD { int chroot(char *path); }
-62 MCOMPAT POSIX { int fstat(int fd, struct ostat *sb); }
-63 MCOMPAT BSD { int getkerninfo(int op, char *where, size_t *size, \
- int arg); } getkerninfo getkerninfo_args int
-64 MCOMPAT BSD { int getpagesize(void); } \
- getpagesize getpagesize_args int
-65 STD BSD { int msync(void *addr, size_t len, int flags); }
-66 MSTD BSD { int vfork(void); }
+46 UNIMPL POSIX osigaction
+47 MNOPROTO POSIX { gid_t getgid(void); }
+48 UNIMPL POSIX osigprocmask
+49 MNOPROTO BSD { int getlogin(char *namebuf, u_int namelen); }
+50 MNOPROTO BSD { int setlogin(char *namebuf); }
+51 MNOPROTO BSD { int acct(char *path); }
+52 MNOPROTO POSIX { int sigpending(void); }
+53 STD BSD { int ia32_sigaltstack(struct sigaltstack32 *ss, struct sigaltstack32 *oss); }
+54 MNOPROTO POSIX { int ioctl(int fd, u_long com, caddr_t data); }
+55 MNOPROTO BSD { int reboot(int opt); }
+56 NOPROTO POSIX { int revoke(char *path); }
+57 NOPROTO POSIX { int symlink(char *path, char *link); }
+58 NOPROTO POSIX { int readlink(char *path, char *buf, int count); }
+59 STD POSIX { int ia32_execve(char *fname, u_int32_t *argv, u_int32_t *envv); }
+60 MNOPROTO POSIX { int umask(int newmask); } umask umask_args int
+61 NOPROTO BSD { int chroot(char *path); }
+62 OBSOL POSIX ofstat
+63 OBSOL BSD ogetkerninfo
+64 OBSOL BSD ogetpagesize
+65 OBSOL BSD omsync
+66 OBSOL BSD ovfork
67 OBSOL NOHIDE vread
68 OBSOL NOHIDE vwrite
-69 MSTD BSD { int sbrk(int incr); }
-70 MSTD BSD { int sstk(int incr); }
-71 MCOMPAT BSD { int mmap(void *addr, int len, int prot, \
- int flags, int fd, long pos); }
-72 MSTD BSD { int ovadvise(int anom); } vadvise ovadvise_args int
-73 MSTD BSD { int munmap(void *addr, size_t len); }
-74 MSTD BSD { int mprotect(const void *addr, size_t len, int prot); }
-75 MSTD BSD { int madvise(void *addr, size_t len, int behav); }
+69 MNOPROTO BSD { int sbrk(int incr); }
+70 MNOPROTO BSD { int sstk(int incr); }
+71 OBSOL BSD ommap
+72 MNOPROTO BSD { int ovadvise(int anom); } vadvise ovadvise_args int
+73 MNOPROTO BSD { int munmap(void *addr, size_t len); }
+74 MNOPROTO BSD { int mprotect(const void *addr, size_t len, int prot); }
+75 MNOPROTO BSD { int madvise(void *addr, size_t len, int behav); }
76 OBSOL NOHIDE vhangup
77 OBSOL NOHIDE vlimit
-78 MSTD BSD { int mincore(const void *addr, size_t len, \
+78 MNOPROTO BSD { int mincore(const void *addr, size_t len, \
char *vec); }
-79 MSTD POSIX { int getgroups(u_int gidsetsize, gid_t *gidset); }
-80 MSTD POSIX { int setgroups(u_int gidsetsize, gid_t *gidset); }
-81 MSTD POSIX { int getpgrp(void); }
-82 MSTD POSIX { int setpgid(int pid, int pgid); }
-83 MSTD BSD { int setitimer(u_int which, struct itimerval *itv, \
- struct itimerval *oitv); }
-84 MCOMPAT BSD { int wait(void); }
-85 MSTD BSD { int swapon(char *name); }
-86 MSTD BSD { int getitimer(u_int which, struct itimerval *itv); }
-87 MCOMPAT BSD { int gethostname(char *hostname, u_int len); } \
- gethostname gethostname_args int
-88 MCOMPAT BSD { int sethostname(char *hostname, u_int len); } \
- sethostname sethostname_args int
-89 MSTD BSD { int getdtablesize(void); }
-90 MSTD POSIX { int dup2(u_int from, u_int to); }
+79 MNOPROTO POSIX { int getgroups(u_int gidsetsize, gid_t *gidset); }
+80 MNOPROTO POSIX { int setgroups(u_int gidsetsize, gid_t *gidset); }
+81 MNOPROTO POSIX { int getpgrp(void); }
+82 MNOPROTO POSIX { int setpgid(int pid, int pgid); }
+83 STD BSD { int ia32_setitimer(u_int which, \
+ struct itimerval32 *itv, \
+ struct itimerval32 *oitv); }
+84 OBSOL BSD owait
+85 OBSOL BSD oswapon
+86 OBSOL BSD ogetitimer
+87 OBSOL BSD ogethostname
+88 OBSOL BSD osethostname
+89 MNOPROTO BSD { int getdtablesize(void); }
+90 MNOPROTO POSIX { int dup2(u_int from, u_int to); }
91 UNIMPL BSD getdopt
-92 MSTD POSIX { int fcntl(int fd, int cmd, long arg); }
+92 MNOPROTO POSIX { int fcntl(int fd, int cmd, long arg); }
; XXX should be { int fcntl(int fd, int cmd, ...); }
; but we're not ready for varargs.
; XXX man page says `int arg' too.
-93 MSTD BSD { int select(int nd, fd_set *in, fd_set *ou, \
- fd_set *ex, struct timeval *tv); }
+93 STD BSD { int ia32_select(int nd, fd_set *in, fd_set *ou, \
+ fd_set *ex, struct timeval32 *tv); }
+; XXX need to override for big-endian - little-endian should work fine.
94 UNIMPL BSD setdopt
-95 STD POSIX { int fsync(int fd); }
-96 MSTD BSD { int setpriority(int which, int who, int prio); }
-97 MSTD BSD { int socket(int domain, int type, int protocol); }
-98 MSTD BSD { int connect(int s, caddr_t name, int namelen); }
-99 MCPT_NOA BSD { int accept(int s, caddr_t name, int *anamelen); } \
+95 NOPROTO POSIX { int fsync(int fd); }
+96 MNOPROTO BSD { int setpriority(int which, int who, int prio); }
+97 MNOPROTO BSD { int socket(int domain, int type, int protocol); }
+98 MNOPROTO BSD { int connect(int s, caddr_t name, int namelen); }
+99 MNOPROTO BSD { int accept(int s, caddr_t name, int *anamelen); } \
accept accept_args int
-100 MSTD BSD { int getpriority(int which, int who); }
-101 MCOMPAT BSD { int send(int s, caddr_t buf, int len, int flags); }
-102 MCOMPAT BSD { int recv(int s, caddr_t buf, int len, int flags); }
-103 STD BSD { int osigreturn(struct osigcontext *sigcntxp); }
-104 MSTD BSD { int bind(int s, caddr_t name, int namelen); }
-105 MSTD BSD { int setsockopt(int s, int level, int name, \
+100 MNOPROTO BSD { int getpriority(int which, int who); }
+101 OBSOL BSD osend
+102 OBSOL BSD orecv
+103 OBSOL BSD osigreturn
+104 MNOPROTO BSD { int bind(int s, caddr_t name, int namelen); }
+105 MNOPROTO BSD { int setsockopt(int s, int level, int name, \
caddr_t val, int valsize); }
-106 MSTD BSD { int listen(int s, int backlog); }
+106 MNOPROTO BSD { int listen(int s, int backlog); }
107 OBSOL NOHIDE vtimes
-108 MCOMPAT BSD { int sigvec(int signum, struct sigvec *nsv, \
- struct sigvec *osv); }
-109 MCOMPAT BSD { int sigblock(int mask); }
-110 MCOMPAT BSD { int sigsetmask(int mask); }
-111 MCOMPAT POSIX { int sigsuspend(osigset_t mask); }
-; XXX note nonstandard (bogus) calling convention - the libc stub passes
-; us the mask, not a pointer to it.
-112 MCOMPAT BSD { int sigstack(struct sigstack *nss, \
- struct sigstack *oss); }
-113 MCOMPAT BSD { int recvmsg(int s, struct omsghdr *msg, int flags); }
-114 MCOMPAT BSD { int sendmsg(int s, caddr_t msg, int flags); }
+108 OBSOL BSD osigvec
+109 OBSOL BSD osigblock
+110 OBSOL BSD osigsetmask
+111 OBSOL POSIX osigsuspend
+112 OBSOL BSD osigstack
+113 OBSOL BSD orecvmsg
+114 OBSOL BSD osendmsg
115 OBSOL NOHIDE vtrace
-116 MSTD BSD { int gettimeofday(struct timeval *tp, \
+116 STD BSD { int ia32_gettimeofday(struct timeval32 *tp, \
struct timezone *tzp); }
-117 MSTD BSD { int getrusage(int who, struct rusage *rusage); }
-118 MSTD BSD { int getsockopt(int s, int level, int name, \
+117 STD BSD { int ia32_getrusage(int who, struct rusage32 *rusage); }
+118 MNOPROTO BSD { int getsockopt(int s, int level, int name, \
caddr_t val, int *avalsize); }
119 UNIMPL NOHIDE resuba (BSD/OS 2.x)
-120 MSTD BSD { int readv(int fd, struct iovec *iovp, u_int iovcnt); }
-121 MSTD BSD { int writev(int fd, struct iovec *iovp, \
+120 STD BSD { int ia32_readv(int fd, struct iovec32 *iovp, u_int iovcnt); }
+121 STD BSD { int ia32_writev(int fd, struct iovec32 *iovp, \
u_int iovcnt); }
-122 MSTD BSD { int settimeofday(struct timeval *tv, \
+122 STD BSD { int ia32_settimeofday(struct timeval32 *tv, \
struct timezone *tzp); }
-123 STD BSD { int fchown(int fd, int uid, int gid); }
-124 STD BSD { int fchmod(int fd, int mode); }
-125 MCPT_NOA BSD { int recvfrom(int s, caddr_t buf, size_t len, \
+123 NOPROTO BSD { int fchown(int fd, int uid, int gid); }
+124 NOPROTO BSD { int fchmod(int fd, int mode); }
+125 MNOPROTO BSD { int recvfrom(int s, caddr_t buf, size_t len, \
int flags, caddr_t from, int *fromlenaddr); } \
recvfrom recvfrom_args int
-126 MSTD BSD { int setreuid(int ruid, int euid); }
-127 MSTD BSD { int setregid(int rgid, int egid); }
-128 STD POSIX { int rename(char *from, char *to); }
-129 COMPAT BSD { int truncate(char *path, long length); }
-130 COMPAT BSD { int ftruncate(int fd, long length); }
-131 MSTD BSD { int flock(int fd, int how); }
-132 STD POSIX { int mkfifo(char *path, int mode); }
-133 MSTD BSD { int sendto(int s, caddr_t buf, size_t len, \
+126 MNOPROTO BSD { int setreuid(int ruid, int euid); }
+127 MNOPROTO BSD { int setregid(int rgid, int egid); }
+128 NOPROTO POSIX { int rename(char *from, char *to); }
+129 OBSOL BSD otruncate
+130 OBSOL BSD ftruncate
+131 MNOPROTO BSD { int flock(int fd, int how); }
+132 NOPROTO POSIX { int mkfifo(char *path, int mode); }
+133 MNOPROTO BSD { int sendto(int s, caddr_t buf, size_t len, \
int flags, caddr_t to, int tolen); }
-134 MSTD BSD { int shutdown(int s, int how); }
-135 MSTD BSD { int socketpair(int domain, int type, int protocol, \
+134 MNOPROTO BSD { int shutdown(int s, int how); }
+135 MNOPROTO BSD { int socketpair(int domain, int type, int protocol, \
int *rsv); }
-136 STD POSIX { int mkdir(char *path, int mode); }
-137 STD POSIX { int rmdir(char *path); }
-138 STD BSD { int utimes(char *path, struct timeval *tptr); }
+136 NOPROTO POSIX { int mkdir(char *path, int mode); }
+137 NOPROTO POSIX { int rmdir(char *path); }
+138 STD BSD { int ia32_utimes(char *path, \
+ struct timeval32 *tptr); }
139 OBSOL NOHIDE 4.2 sigreturn
-140 MSTD BSD { int adjtime(struct timeval *delta, \
- struct timeval *olddelta); }
-141 MCOMPAT BSD { int getpeername(int fdes, caddr_t asa, int *alen); }
-142 MCOMPAT BSD { long gethostid(void); }
-143 MCOMPAT BSD { int sethostid(long hostid); }
-144 MCOMPAT BSD { int getrlimit(u_int which, struct orlimit *rlp); }
-145 MCOMPAT BSD { int setrlimit(u_int which, struct orlimit *rlp); }
-146 MCOMPAT BSD { int killpg(int pgid, int signum); }
-147 MSTD POSIX { int setsid(void); }
-148 STD BSD { int quotactl(char *path, int cmd, int uid, \
+140 STD BSD { int ia32_adjtime(struct timeval32 *delta, \
+ struct timeval32 *olddelta); }
+141 OBSOL BSD ogetpeername
+142 OBSOL BSD ogethostid
+143 OBSOL BSD sethostid
+144 OBSOL BSD getrlimit
+145 OBSOL BSD setrlimit
+146 OBSOL BSD killpg
+147 MNOPROTO POSIX { int setsid(void); }
+148 NOPROTO BSD { int quotactl(char *path, int cmd, int uid, \
caddr_t arg); }
-149 MCOMPAT BSD { int quota(void); }
-150 MCPT_NOA BSD { int getsockname(int fdec, caddr_t asa, int *alen); }\
- getsockname getsockname_args int
+149 OBSOL BSD oquota
+150 OBSOL BSD ogetsockname
; Syscalls 151-180 inclusive are reserved for vendor-specific
; system calls. (This includes various calls added for compatibity
@@ -247,136 +239,138 @@
153 UNIMPL NOHIDE asyncdaemon (BSD/OS 2.x)
154 UNIMPL NOHIDE nosys
; 155 is initialized by the NFS code, if present.
-155 MNOIMPL BSD { int nfssvc(int flag, caddr_t argp); }
-156 COMPAT BSD { int getdirentries(int fd, char *buf, u_int count, \
+155 UNIMPL NOHIDE nfssvc
+156 NOPROTO BSD { int getdirentries(int fd, char *buf, u_int count, \
long *basep); }
-157 STD BSD { int statfs(char *path, struct statfs *buf); }
-158 STD BSD { int fstatfs(int fd, struct statfs *buf); }
+157 STD BSD { int ia32_statfs(char *path, struct statfs32 *buf); }
+158 STD BSD { int ia32_fstatfs(int fd, struct statfs32 *buf); }
159 UNIMPL NOHIDE nosys
160 UNIMPL NOHIDE nosys
-161 STD BSD { int getfh(char *fname, struct fhandle *fhp); }
-162 MSTD BSD { int getdomainname(char *domainname, int len); }
-163 MSTD BSD { int setdomainname(char *domainname, int len); }
-164 MSTD BSD { int uname(struct utsname *name); }
-165 STD BSD { int sysarch(int op, char *parms); }
-166 MSTD BSD { int rtprio(int function, pid_t pid, \
+161 NOPROTO BSD { int getfh(char *fname, struct fhandle *fhp); }
+162 MNOPROTO BSD { int getdomainname(char *domainname, int len); }
+163 MNOPROTO BSD { int setdomainname(char *domainname, int len); }
+164 MNOPROTO BSD { int uname(struct utsname *name); }
+165 NOPROTO BSD { int sysarch(int op, char *parms); }
+166 MNOPROTO BSD { int rtprio(int function, pid_t pid, \
struct rtprio *rtp); }
167 UNIMPL NOHIDE nosys
168 UNIMPL NOHIDE nosys
-; 169 is initialized by the SYSVSEM code if present or loaded
-169 MNOSTD BSD { int semsys(int which, int a2, int a3, int a4, \
+169 STD BSD { int ia32_semsys(int which, int a2, int a3, int a4, \
int a5); }
-; 169 is initialized by the SYSVMSG code if present or loaded
-; XXX should be { int semsys(int which, ...); }
-170 MNOSTD BSD { int msgsys(int which, int a2, int a3, int a4, \
+170 STD BSD { int ia32_msgsys(int which, int a2, int a3, int a4, \
int a5, int a6); }
-; 169 is initialized by the SYSVSHM code if present or loaded
-; XXX should be { int msgsys(int which, ...); }
-171 MNOSTD BSD { int shmsys(int which, int a2, int a3, int a4); }
-; XXX should be { int shmsys(int which, ...); }
+171 STD BSD { int ia32_shmsys(int which, int a2, int a3, int a4); }
172 UNIMPL NOHIDE nosys
-173 MSTD POSIX { ssize_t pread(int fd, void *buf, size_t nbyte, \
- int pad, off_t offset); }
-174 MSTD POSIX { ssize_t pwrite(int fd, const void *buf, \
- size_t nbyte, int pad, off_t offset); }
+173 STD POSIX { ssize_t ia32_pread(int fd, void *buf, size_t nbyte, \
+ int pad, u_int32_t offsetlo, u_int32_t offsethi); }
+; XXX note - bigendian is different
+174 STD POSIX { ssize_t ia32_pwrite(int fd, const void *buf, \
+ size_t nbyte, int pad, u_int32_t offsetlo, \
+ u_int32_t offsethi); }
+; XXX note - bigendian is different
175 UNIMPL NOHIDE nosys
-176 MSTD BSD { int ntp_adjtime(struct timex *tp); }
+176 MNOPROTO BSD { int ntp_adjtime(struct timex *tp); }
177 UNIMPL NOHIDE sfork (BSD/OS 2.x)
178 UNIMPL NOHIDE getdescriptor (BSD/OS 2.x)
179 UNIMPL NOHIDE setdescriptor (BSD/OS 2.x)
180 UNIMPL NOHIDE nosys
; Syscalls 181-199 are used by/reserved for BSD
-181 MSTD POSIX { int setgid(gid_t gid); }
-182 MSTD BSD { int setegid(gid_t egid); }
-183 MSTD BSD { int seteuid(uid_t euid); }
+181 MNOPROTO POSIX { int setgid(gid_t gid); }
+182 MNOPROTO BSD { int setegid(gid_t egid); }
+183 MNOPROTO BSD { int seteuid(uid_t euid); }
184 UNIMPL BSD lfs_bmapv
185 UNIMPL BSD lfs_markv
186 UNIMPL BSD lfs_segclean
187 UNIMPL BSD lfs_segwait
-188 STD POSIX { int stat(char *path, struct stat *ub); }
-189 MSTD POSIX { int fstat(int fd, struct stat *sb); }
-190 STD POSIX { int lstat(char *path, struct stat *ub); }
-191 STD POSIX { int pathconf(char *path, int name); }
-192 MSTD POSIX { int fpathconf(int fd, int name); }
+188 STD POSIX { int ia32_stat(char *path, struct stat32 *ub); }
+189 STD POSIX { int ia32_fstat(int fd, struct stat32 *ub); }
+190 STD POSIX { int ia32_lstat(char *path, struct stat32 *ub); }
+191 NOPROTO POSIX { int pathconf(char *path, int name); }
+192 MNOPROTO POSIX { int fpathconf(int fd, int name); }
193 UNIMPL NOHIDE nosys
-194 MSTD BSD { int getrlimit(u_int which, \
+194 MNOPROTO BSD { int getrlimit(u_int which, \
struct rlimit *rlp); } \
getrlimit __getrlimit_args int
-195 MSTD BSD { int setrlimit(u_int which, \
+195 MNOPROTO BSD { int setrlimit(u_int which, \
struct rlimit *rlp); } \
setrlimit __setrlimit_args int
-196 STD BSD { int getdirentries(int fd, char *buf, u_int count, \
+196 NOPROTO BSD { int getdirentries(int fd, char *buf, u_int count, \
long *basep); }
-197 MSTD BSD { caddr_t mmap(caddr_t addr, size_t len, int prot, \
- int flags, int fd, int pad, off_t pos); }
-198 STD NOHIDE { int nosys(void); } __syscall __syscall_args int
-199 STD POSIX { off_t lseek(int fd, int pad, off_t offset, \
+197 STD BSD { caddr_t ia32_mmap(caddr_t addr, size_t len, \
+ int prot, int flags, int fd, int pad, \
+ u_int32_t poslo, u_int32_t poshi); }
+198 NOPROTO NOHIDE { int nosys(void); } __syscall __syscall_args int
+; XXX note - bigendian is different
+199 STD POSIX { off_t ia32_lseek(int fd, int pad, \
+ u_int32_t offsetlo, u_int32_t offsethi, \
int whence); }
-200 STD BSD { int truncate(char *path, int pad, off_t length); }
-201 STD BSD { int ftruncate(int fd, int pad, off_t length); }
-202 MSTD BSD { int __sysctl(int *name, u_int namelen, void *old, \
- size_t *oldlenp, void *new, size_t newlen); } \
- __sysctl sysctl_args int
-; properly, __sysctl should be a NOHIDE, but making an exception
-; here allows to avoid one in libc/sys/Makefile.inc.
-203 MSTD BSD { int mlock(const void *addr, size_t len); }
-204 MSTD BSD { int munlock(const void *addr, size_t len); }
-205 STD BSD { int undelete(char *path); }
-206 STD BSD { int futimes(int fd, struct timeval *tptr); }
-207 MSTD BSD { int getpgid(pid_t pid); }
+; XXX note - bigendian is different
+200 STD BSD { int ia32_truncate(char *path, int pad, \
+ u_int32_t lengthlo, u_int32_t lengthhi); }
+; XXX note - bigendian is different
+201 STD BSD { int ia32_ftruncate(int fd, int pad, \
+ u_int32_t lengthlo, u_int32_t lengthhi); }
+202 MSTD BSD { int ia32_sysctl(int *name, u_int namelen, \
+ void *old, u_int32_t *oldlenp, void *new, \
+ u_int32_t newlen); }
+203 MNOPROTO BSD { int mlock(const void *addr, size_t len); }
+204 MNOPROTO BSD { int munlock(const void *addr, size_t len); }
+205 NOPROTO BSD { int undelete(char *path); }
+206 NOPROTO BSD { int futimes(int fd, struct timeval *tptr); }
+207 MNOPROTO BSD { int getpgid(pid_t pid); }
208 UNIMPL NOHIDE newreboot (NetBSD)
-209 MSTD BSD { int poll(struct pollfd *fds, u_int nfds, \
+209 MNOPROTO BSD { int poll(struct pollfd *fds, u_int nfds, \
int timeout); }
;
; The following are reserved for loadable syscalls
;
-210 NODEF NOHIDE lkmnosys lkmnosys nosys_args int
-211 NODEF NOHIDE lkmnosys lkmnosys nosys_args int
-212 NODEF NOHIDE lkmnosys lkmnosys nosys_args int
-213 NODEF NOHIDE lkmnosys lkmnosys nosys_args int
-214 NODEF NOHIDE lkmnosys lkmnosys nosys_args int
-215 NODEF NOHIDE lkmnosys lkmnosys nosys_args int
-216 NODEF NOHIDE lkmnosys lkmnosys nosys_args int
-217 NODEF NOHIDE lkmnosys lkmnosys nosys_args int
-218 NODEF NOHIDE lkmnosys lkmnosys nosys_args int
-219 NODEF NOHIDE lkmnosys lkmnosys nosys_args int
+210 UNIMPL NOHIDE
+211 UNIMPL NOHIDE
+212 UNIMPL NOHIDE
+213 UNIMPL NOHIDE
+214 UNIMPL NOHIDE
+215 UNIMPL NOHIDE
+216 UNIMPL NOHIDE
+217 UNIMPL NOHIDE
+218 UNIMPL NOHIDE
+219 UNIMPL NOHIDE
;
; The following were introduced with NetBSD/4.4Lite-2
; They are initialized by thier respective modules/sysinits
-220 MNOSTD BSD { int __semctl(int semid, int semnum, int cmd, \
+220 MNOPROTO BSD { int __semctl(int semid, int semnum, int cmd, \
union semun *arg); }
-221 MNOSTD BSD { int semget(key_t key, int nsems, int semflg); }
-222 MNOSTD BSD { int semop(int semid, struct sembuf *sops, \
+221 MNOPROTO BSD { int semget(key_t key, int nsems, int semflg); }
+222 MNOPROTO BSD { int semop(int semid, struct sembuf *sops, \
u_int nsops); }
223 UNIMPL NOHIDE semconfig
-224 MNOSTD BSD { int msgctl(int msqid, int cmd, \
+224 MNOPROTO BSD { int msgctl(int msqid, int cmd, \
struct msqid_ds *buf); }
-225 MNOSTD BSD { int msgget(key_t key, int msgflg); }
-226 MNOSTD BSD { int msgsnd(int msqid, void *msgp, size_t msgsz, \
+225 MNOPROTO BSD { int msgget(key_t key, int msgflg); }
+226 MNOPROTO BSD { int msgsnd(int msqid, void *msgp, size_t msgsz, \
int msgflg); }
-227 MNOSTD BSD { int msgrcv(int msqid, void *msgp, size_t msgsz, \
+227 MNOPROTO BSD { int msgrcv(int msqid, void *msgp, size_t msgsz, \
long msgtyp, int msgflg); }
-228 MNOSTD BSD { int shmat(int shmid, void *shmaddr, int shmflg); }
-229 MNOSTD BSD { int shmctl(int shmid, int cmd, \
+228 MNOPROTO BSD { int shmat(int shmid, void *shmaddr, int shmflg); }
+229 MNOPROTO BSD { int shmctl(int shmid, int cmd, \
struct shmid_ds *buf); }
-230 MNOSTD BSD { int shmdt(void *shmaddr); }
-231 MNOSTD BSD { int shmget(key_t key, int size, int shmflg); }
+230 MNOPROTO BSD { int shmdt(void *shmaddr); }
+231 MNOPROTO BSD { int shmget(key_t key, int size, int shmflg); }
;
-232 MSTD POSIX { int clock_gettime(clockid_t clock_id, \
+232 MNOPROTO POSIX { int clock_gettime(clockid_t clock_id, \
struct timespec *tp); }
-233 MSTD POSIX { int clock_settime(clockid_t clock_id, \
+233 MNOPROTO POSIX { int clock_settime(clockid_t clock_id, \
const struct timespec *tp); }
-234 MSTD POSIX { int clock_getres(clockid_t clock_id, \
+234 MNOPROTO POSIX { int clock_getres(clockid_t clock_id, \
struct timespec *tp); }
235 UNIMPL NOHIDE timer_create
236 UNIMPL NOHIDE timer_delete
237 UNIMPL NOHIDE timer_settime
238 UNIMPL NOHIDE timer_gettime
239 UNIMPL NOHIDE timer_getoverrun
-240 MSTD POSIX { int nanosleep(const struct timespec *rqtp, \
+240 MNOPROTO POSIX { int nanosleep(const struct timespec *rqtp, \
struct timespec *rmtp); }
241 UNIMPL NOHIDE nosys
242 UNIMPL NOHIDE nosys
@@ -388,12 +382,12 @@
248 UNIMPL NOHIDE nosys
249 UNIMPL NOHIDE nosys
; syscall numbers initially used in OpenBSD
-250 MSTD BSD { int minherit(void *addr, size_t len, int inherit); }
-251 MSTD BSD { int rfork(int flags); }
-252 MSTD BSD { int openbsd_poll(struct pollfd *fds, u_int nfds, \
+250 MNOPROTO BSD { int minherit(void *addr, size_t len, int inherit); }
+251 MNOPROTO BSD { int rfork(int flags); }
+252 MNOPROTO BSD { int openbsd_poll(struct pollfd *fds, u_int nfds, \
int timeout); }
-253 STD BSD { int issetugid(void); }
-254 STD BSD { int lchown(char *path, int uid, int gid); }
+253 NOPROTO BSD { int issetugid(void); }
+254 NOPROTO BSD { int lchown(char *path, int uid, int gid); }
255 UNIMPL NOHIDE nosys
256 UNIMPL NOHIDE nosys
257 UNIMPL NOHIDE nosys
@@ -411,15 +405,15 @@
269 UNIMPL NOHIDE nosys
270 UNIMPL NOHIDE nosys
271 UNIMPL NOHIDE nosys
-272 STD BSD { int getdents(int fd, char *buf, size_t count); }
+272 NOPROTO BSD { int getdents(int fd, char *buf, size_t count); }
273 UNIMPL NOHIDE nosys
-274 STD BSD { int lchmod(char *path, mode_t mode); }
+274 NOPROTO BSD { int lchmod(char *path, mode_t mode); }
275 NOPROTO BSD { int lchown(char *path, uid_t uid, gid_t gid); } netbsd_lchown lchown_args int
-276 STD BSD { int lutimes(char *path, struct timeval *tptr); }
+276 NOPROTO BSD { int lutimes(char *path, struct timeval *tptr); }
277 MNOPROTO BSD { int msync(void *addr, size_t len, int flags); } netbsd_msync msync_args int
-278 STD BSD { int nstat(char *path, struct nstat *ub); }
-279 MSTD BSD { int nfstat(int fd, struct nstat *sb); }
-280 STD BSD { int nlstat(char *path, struct nstat *ub); }
+278 NOPROTO BSD { int nstat(char *path, struct nstat *ub); }
+279 MNOPROTO BSD { int nfstat(int fd, struct nstat *sb); }
+280 NOPROTO BSD { int nlstat(char *path, struct nstat *ub); }
281 UNIMPL NOHIDE nosys
282 UNIMPL NOHIDE nosys
283 UNIMPL NOHIDE nosys
@@ -437,126 +431,133 @@
295 UNIMPL NOHIDE nosys
296 UNIMPL NOHIDE nosys
; XXX 297 is 300 in NetBSD
-297 STD BSD { int fhstatfs(const struct fhandle *u_fhp, struct statfs *buf); }
-298 STD BSD { int fhopen(const struct fhandle *u_fhp, int flags); }
-299 STD BSD { int fhstat(const struct fhandle *u_fhp, struct stat *sb); }
+297 NOPROTO BSD { int fhstatfs(const struct fhandle *u_fhp, struct statfs *buf); }
+298 NOPROTO BSD { int fhopen(const struct fhandle *u_fhp, int flags); }
+299 NOPROTO BSD { int fhstat(const struct fhandle *u_fhp, struct stat *sb); }
; syscall numbers for FreeBSD
-300 MSTD BSD { int modnext(int modid); }
-301 MSTD BSD { int modstat(int modid, struct module_stat* stat); }
-302 MSTD BSD { int modfnext(int modid); }
-303 MSTD BSD { int modfind(const char *name); }
-304 MSTD BSD { int kldload(const char *file); }
-305 MSTD BSD { int kldunload(int fileid); }
-306 MSTD BSD { int kldfind(const char *file); }
-307 MSTD BSD { int kldnext(int fileid); }
-308 MSTD BSD { int kldstat(int fileid, struct kld_file_stat* stat); }
-309 MSTD BSD { int kldfirstmod(int fileid); }
-310 MSTD BSD { int getsid(pid_t pid); }
-311 MSTD BSD { int setresuid(uid_t ruid, uid_t euid, uid_t suid); }
-312 MSTD BSD { int setresgid(gid_t rgid, gid_t egid, gid_t sgid); }
+300 MNOPROTO BSD { int modnext(int modid); }
+301 MNOPROTO BSD { int modstat(int modid, struct module_stat* stat); }
+302 MNOPROTO BSD { int modfnext(int modid); }
+303 MNOPROTO BSD { int modfind(const char *name); }
+304 MNOPROTO BSD { int kldload(const char *file); }
+305 MNOPROTO BSD { int kldunload(int fileid); }
+306 MNOPROTO BSD { int kldfind(const char *file); }
+307 MNOPROTO BSD { int kldnext(int fileid); }
+308 MNOPROTO BSD { int kldstat(int fileid, struct kld_file_stat* stat); }
+309 MNOPROTO BSD { int kldfirstmod(int fileid); }
+310 MNOPROTO BSD { int getsid(pid_t pid); }
+311 MNOPROTO BSD { int setresuid(uid_t ruid, uid_t euid, uid_t suid); }
+312 MNOPROTO BSD { int setresgid(gid_t rgid, gid_t egid, gid_t sgid); }
313 OBSOL NOHIDE signanosleep
-314 NOSTD BSD { int aio_return(struct aiocb *aiocbp); }
-315 NOSTD BSD { int aio_suspend(struct aiocb * const * aiocbp, int nent, const struct timespec *timeout); }
-316 NOSTD BSD { int aio_cancel(int fd, struct aiocb *aiocbp); }
-317 NOSTD BSD { int aio_error(struct aiocb *aiocbp); }
-318 NOSTD BSD { int aio_read(struct aiocb *aiocbp); }
-319 NOSTD BSD { int aio_write(struct aiocb *aiocbp); }
-320 NOSTD BSD { int lio_listio(int mode, struct aiocb * const *acb_list, int nent, struct sigevent *sig); }
-321 MSTD BSD { int yield(void); }
+314 UNIMPL NOHIDE aio_return
+315 UNIMPL NOHIDE aio_suspend
+316 UNIMPL NOHIDE aio_cancel
+317 UNIMPL NOHIDE aio_error
+318 UNIMPL NOHIDE aio_read
+319 UNIMPL NOHIDE aio_write
+320 UNIMPL NOHIDE lio_listio
+321 MNOPROTO BSD { int yield(void); }
322 OBSOL NOHIDE thr_sleep
323 OBSOL NOHIDE thr_wakeup
-324 MSTD BSD { int mlockall(int how); }
-325 MSTD BSD { int munlockall(void); }
-326 STD BSD { int __getcwd(u_char *buf, u_int buflen); }
+324 MNOPROTO BSD { int mlockall(int how); }
+325 MNOPROTO BSD { int munlockall(void); }
+326 NOPROTO BSD { int __getcwd(u_char *buf, u_int buflen); }
-327 MSTD POSIX { int sched_setparam (pid_t pid, const struct sched_param *param); }
-328 MSTD POSIX { int sched_getparam (pid_t pid, struct sched_param *param); }
+327 MNOPROTO POSIX { int sched_setparam (pid_t pid, const struct sched_param *param); }
+328 MNOPROTO POSIX { int sched_getparam (pid_t pid, struct sched_param *param); }
-329 MSTD POSIX { int sched_setscheduler (pid_t pid, int policy, const struct sched_param *param); }
-330 MSTD POSIX { int sched_getscheduler (pid_t pid); }
+329 MNOPROTO POSIX { int sched_setscheduler (pid_t pid, int policy, const struct sched_param *param); }
+330 MNOPROTO POSIX { int sched_getscheduler (pid_t pid); }
-331 MSTD POSIX { int sched_yield (void); }
-332 MSTD POSIX { int sched_get_priority_max (int policy); }
-333 MSTD POSIX { int sched_get_priority_min (int policy); }
-334 MSTD POSIX { int sched_rr_get_interval (pid_t pid, struct timespec *interval); }
-335 STD BSD { int utrace(const void *addr, size_t len); }
-336 MSTD BSD { int sendfile(int fd, int s, off_t offset, size_t nbytes, \
- struct sf_hdtr *hdtr, off_t *sbytes, int flags); }
-337 STD BSD { int kldsym(int fileid, int cmd, void *data); }
-338 MSTD BSD { int jail(struct jail *jail); }
+331 MNOPROTO POSIX { int sched_yield (void); }
+332 MNOPROTO POSIX { int sched_get_priority_max (int policy); }
+333 MNOPROTO POSIX { int sched_get_priority_min (int policy); }
+334 MNOPROTO POSIX { int sched_rr_get_interval (pid_t pid, struct timespec *interval); }
+335 NOPROTO BSD { int utrace(const void *addr, size_t len); }
+; XXX note - bigendian is different
+336 MSTD BSD { int ia32_sendfile(int fd, int s, u_int32_t offsetlo, \
+ u_int32_t offsethi, size_t nbytes, \
+ struct sf_hdtr *hdtr, off_t *sbytes, int flags); }
+337 NOPROTO BSD { int kldsym(int fileid, int cmd, void *data); }
+338 MNOPROTO BSD { int jail(struct jail *jail); }
339 UNIMPL BSD pioctl
-340 MSTD POSIX { int sigprocmask(int how, const sigset_t *set, \
+340 MNOPROTO POSIX { int sigprocmask(int how, const sigset_t *set, \
sigset_t *oset); }
-341 MSTD POSIX { int sigsuspend(const sigset_t *sigmask); }
-342 MSTD POSIX { int sigaction(int sig, const struct sigaction *act, \
- struct sigaction *oact); }
-343 MSTD POSIX { int sigpending(sigset_t *set); }
-344 STD BSD { int sigreturn(const struct __ucontext *sigcntxp); }
+341 MNOPROTO POSIX { int sigsuspend(const sigset_t *sigmask); }
+342 STD POSIX { int ia32_sigaction(int sig, \
+ struct sigaction32 *act, \
+ struct sigaction32 *oact); }
+343 MNOPROTO POSIX { int sigpending(sigset_t *set); }
+344 MNOPROTO BSD { int sigreturn(const struct __ucontext *sigcntxp); }
345 UNIMPL NOHIDE sigtimedwait
346 UNIMPL NOHIDE sigwaitinfo
-347 MSTD BSD { int __acl_get_file(const char *path, \
+347 MNOPROTO BSD { int __acl_get_file(const char *path, \
acl_type_t type, struct acl *aclp); }
-348 MSTD BSD { int __acl_set_file(const char *path, \
+348 MNOPROTO BSD { int __acl_set_file(const char *path, \
acl_type_t type, struct acl *aclp); }
-349 MSTD BSD { int __acl_get_fd(int filedes, acl_type_t type, \
+349 MNOPROTO BSD { int __acl_get_fd(int filedes, acl_type_t type, \
struct acl *aclp); }
-350 MSTD BSD { int __acl_set_fd(int filedes, acl_type_t type, \
+350 MNOPROTO BSD { int __acl_set_fd(int filedes, acl_type_t type, \
struct acl *aclp); }
-351 MSTD BSD { int __acl_delete_file(const char *path, \
+351 MNOPROTO BSD { int __acl_delete_file(const char *path, \
acl_type_t type); }
-352 MSTD BSD { int __acl_delete_fd(int filedes, acl_type_t type); }
-353 MSTD BSD { int __acl_aclcheck_file(const char *path, \
+352 MNOPROTO BSD { int __acl_delete_fd(int filedes, acl_type_t type); }
+353 MNOPROTO BSD { int __acl_aclcheck_file(const char *path, \
acl_type_t type, struct acl *aclp); }
-354 MSTD BSD { int __acl_aclcheck_fd(int filedes, acl_type_t type, \
+354 MNOPROTO BSD { int __acl_aclcheck_fd(int filedes, acl_type_t type, \
struct acl *aclp); }
-355 STD BSD { int extattrctl(const char *path, int cmd, \
+355 NOPROTO BSD { int extattrctl(const char *path, int cmd, \
const char *filename, int attrnamespace, \
const char *attrname); }
-356 STD BSD { int extattr_set_file(const char *path, \
+356 NOPROTO BSD { int extattr_set_file(const char *path, \
int attrnamespace, const char *attrname, \
void *data, size_t nbytes); }
-357 STD BSD { ssize_t extattr_get_file(const char *path, \
+357 NOPROTO BSD { ssize_t extattr_get_file(const char *path, \
int attrnamespace, const char *attrname, \
void *data, size_t nbytes); }
-358 STD BSD { int extattr_delete_file(const char *path, \
+358 NOPROTO BSD { int extattr_delete_file(const char *path, \
int attrnamespace, const char *attrname); }
-359 NOSTD BSD { int aio_waitcomplete(struct aiocb **aiocbp, struct timespec *timeout); }
-360 MSTD BSD { int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); }
-361 MSTD BSD { int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); }
-362 MSTD BSD { int kqueue(void); }
-363 MSTD BSD { int kevent(int fd, \
+359 UNIMPL NOHIDE aio_waitcomplete
+360 MNOPROTO BSD { int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); }
+361 MNOPROTO BSD { int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); }
+362 MNOPROTO BSD { int kqueue(void); }
+363 MNOPROTO BSD { int kevent(int fd, \
const struct kevent *changelist, int nchanges, \
struct kevent *eventlist, int nevents, \
const struct timespec *timeout); }
-364 STD BSD { int __cap_get_proc(struct cap *cap_p); }
-365 STD BSD { int __cap_set_proc(struct cap *cap_p); }
-366 STD BSD { int __cap_get_fd(int fd, struct cap *cap_p); }
-367 STD BSD { int __cap_get_file(const char *path_p, struct cap *cap_p); }
-368 STD BSD { int __cap_set_fd(int fd, struct cap *cap_p); }
-369 STD BSD { int __cap_set_file(const char *path_p, struct cap *cap_p); }
-370 NODEF NOHIDE lkmressys lkmressys nosys_args int
-371 STD BSD { int extattr_set_fd(int fd, int attrnamespace, \
+364 UNIMPL NOHIDE __cap_get_proc
+365 UNIMPL NOHIDE __cap_set_proc
+366 UNIMPL NOHIDE __cap_get_fd
+367 UNIMPL NOHIDE __cap_get_file
+368 UNIMPL NOHIDE __cap_set_fd
+369 UNIMPL NOHIDE __cap_set_file
+370 UNIMPL NOHIDE lkmressys
+371 NOPROTO BSD { int extattr_set_fd(int fd, int attrnamespace, \
const char *attrname, void *data, \
size_t nbytes); }
-372 STD BSD { ssize_t extattr_get_fd(int fd, int attrnamespace, \
+372 NOPROTO BSD { ssize_t extattr_get_fd(int fd, int attrnamespace, \
const char *attrname, void *data, size_t nbytes); }
-373 STD BSD { int extattr_delete_fd(int fd, int attrnamespace, \
+373 NOPROTO BSD { int extattr_delete_fd(int fd, int attrnamespace, \
const char *attrname); }
-374 MSTD BSD { int __setugid(int flag); }
-375 NOIMPL BSD { int nfsclnt(int flag, caddr_t argp); }
-376 STD BSD { int eaccess(char *path, int flags); }
+374 MNOPROTO BSD { int __setugid(int flag); }
+375 UNIMPL BSD nfsclnt
+376 NOPROTO BSD { int eaccess(char *path, int flags); }
377 UNIMPL BSD afs_syscall
-378 STD BSD { int nmount(struct iovec *iovp, unsigned int iovcnt, \
+378 NOPROTO BSD { int nmount(struct iovec *iovp, unsigned int iovcnt, \
int flags); }
-379 STD BSD { int kse_exit(void); }
-380 STD BSD { int kse_wakeup(void); }
-381 STD BSD { int kse_new(struct kse_mailbox * mbx, \
+379 NOPROTO BSD { int kse_exit(void); }
+380 NOPROTO BSD { int kse_wakeup(void); }
+381 NOPROTO BSD { int kse_new(struct kse_mailbox * mbx, \
int new_grp_flag); }
-382 STD BSD { int thread_wakeup(struct thread_mailbox *tmbx); }
-383 STD BSD { int kse_yield(void); }
+382 NOPROTO BSD { int thread_wakeup(struct thread_mailbox *tmbx); }
+383 NOPROTO BSD { int kse_yield(void); }
384 UNIMPL BSD __mac_get_proc
385 UNIMPL BSD __mac_set_proc
386 UNIMPL BSD __mac_get_fd
387 UNIMPL BSD __mac_get_file
388 UNIMPL BSD __mac_set_fd
389 UNIMPL BSD __mac_set_file
+390 NOPROTO BSD { int kenv(int what, const char *name, char *value, \
+ int len); }
+391 NOPROTO BSD { int lchflags(const char *path, int flags); }
+392 NOPROTO BSD { int uuidgen(struct uuid *store, int count); }
diff --git a/sys/compat/ia32/ia32_sysvec.c b/sys/compat/ia32/ia32_sysvec.c
new file mode 100644
index 000000000000..06e6505a4b3e
--- /dev/null
+++ b/sys/compat/ia32/ia32_sysvec.c
@@ -0,0 +1,365 @@
+/*-
+ * Copyright (c) 2002 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#define __ELF_WORD_SIZE 32
+
+#include <sys/param.h>
+#include <sys/exec.h>
+#include <sys/fcntl.h>
+#include <sys/imgact.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/mman.h>
+#include <sys/namei.h>
+#include <sys/pioctl.h>
+#include <sys/proc.h>
+#include <sys/procfs.h>
+#include <sys/resourcevar.h>
+#include <sys/systm.h>
+#include <sys/signalvar.h>
+#include <sys/stat.h>
+#include <sys/sx.h>
+#include <sys/syscall.h>
+#include <sys/sysctl.h>
+#include <sys/sysent.h>
+#include <sys/vnode.h>
+#include <sys/imgact_elf.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_extern.h>
+
+#include <ia64/ia32/ia32_util.h>
+#include <i386/include/psl.h>
+#include <i386/include/segments.h>
+#include <i386/include/specialreg.h>
+#include <machine/frame.h>
+#include <machine/md_var.h>
+
+static register_t *ia32_copyout_strings(struct image_params *imgp);
+static void ia32_setregs(struct thread *td, u_long entry, u_long stack,
+ u_long ps_strings);
+
+extern struct sysent ia32_sysent[];
+
+static char ia32_sigcode[] = {
+ 0xff, 0x54, 0x24, 0x10, /* call *SIGF_HANDLER(%esp) */
+ 0x8d, 0x44, 0x24, 0x14, /* lea SIGF_UC(%esp),%eax */
+ 0x50, /* pushl %eax */
+ 0xf7, 0x40, 0x54, 0x00, 0x00, 0x02, 0x02, /* testl $PSL_VM,UC_EFLAGS(%eax) */
+ 0x75, 0x03, /* jne 9f */
+ 0x8e, 0x68, 0x14, /* movl UC_GS(%eax),%gs */
+ 0xb8, 0x57, 0x01, 0x00, 0x00, /* 9: movl $SYS_sigreturn,%eax */
+ 0x50, /* pushl %eax */
+ 0xcd, 0x80, /* int $0x80 */
+ 0xeb, 0xfe, /* 0: jmp 0b */
+ 0, 0, 0, 0
+};
+static int ia32_szsigcode = sizeof(ia32_sigcode) & ~3;
+
+struct sysentvec ia32_freebsd_sysvec = {
+ SYS_MAXSYSCALL,
+ ia32_sysent,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ elf32_freebsd_fixup,
+ sendsig,
+ ia32_sigcode,
+ &ia32_szsigcode,
+ 0,
+ "FreeBSD ELF",
+ elf32_coredump,
+ NULL,
+ MINSIGSTKSZ,
+ 4096,
+ IA32_USRSTACK,
+ IA32_USRSTACK,
+ ia32_copyout_strings,
+ ia32_setregs
+};
+
+static Elf32_Brandinfo ia32_brand_info = {
+ ELFOSABI_FREEBSD,
+ EM_386,
+ "FreeBSD",
+ "/compat/ia32",
+ "/usr/libexec/ld-elf.so.1",
+ &ia32_freebsd_sysvec
+ };
+
+SYSINIT(ia32, SI_SUB_EXEC, SI_ORDER_ANY,
+ (sysinit_cfunc_t) elf32_insert_brand_entry,
+ &ia32_brand_info);
+
+static register_t *
+ia32_copyout_strings(struct image_params *imgp)
+{
+ int argc, envc;
+ u_int32_t *vectp;
+ char *stringp, *destp;
+ u_int32_t *stack_base;
+ struct ia32_ps_strings *arginfo;
+ int szsigcode;
+
+ /*
+ * Calculate string base and vector table pointers.
+ * Also deal with signal trampoline code for this exec type.
+ */
+ arginfo = (struct ia32_ps_strings *)IA32_PS_STRINGS;
+ szsigcode = *(imgp->proc->p_sysent->sv_szsigcode);
+ destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE -
+ roundup((ARG_MAX - imgp->stringspace), sizeof(char *));
+
+ /*
+ * install sigcode
+ */
+ if (szsigcode)
+ copyout(imgp->proc->p_sysent->sv_sigcode,
+ ((caddr_t)arginfo - szsigcode), szsigcode);
+
+ /*
+ * If we have a valid auxargs ptr, prepare some room
+ * on the stack.
+ */
+ if (imgp->auxargs) {
+ /*
+ * 'AT_COUNT*2' is size for the ELF Auxargs data. This is for
+ * lower compatibility.
+ */
+ imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size
+ : (AT_COUNT * 2);
+ /*
+ * The '+ 2' is for the null pointers at the end of each of
+ * the arg and env vector sets,and imgp->auxarg_size is room
+ * for argument of Runtime loader.
+ */
+ vectp = (u_int32_t *) (destp - (imgp->argc + imgp->envc + 2 +
+ imgp->auxarg_size) * sizeof(u_int32_t));
+
+ } else
+ /*
+ * The '+ 2' is for the null pointers at the end of each of
+ * the arg and env vector sets
+ */
+ vectp = (u_int32_t *)
+ (destp - (imgp->argc + imgp->envc + 2) * sizeof(u_int32_t));
+
+ /*
+ * vectp also becomes our initial stack base
+ */
+ stack_base = vectp;
+
+ stringp = imgp->stringbase;
+ argc = imgp->argc;
+ envc = imgp->envc;
+
+ /*
+ * Copy out strings - arguments and environment.
+ */
+ copyout(stringp, destp, ARG_MAX - imgp->stringspace);
+
+ /*
+ * Fill in "ps_strings" struct for ps, w, etc.
+ */
+ suword32(&arginfo->ps_argvstr, (u_int32_t)(intptr_t)vectp);
+ suword32(&arginfo->ps_nargvstr, argc);
+
+ /*
+ * Fill in argument portion of vector table.
+ */
+ for (; argc > 0; --argc) {
+ suword32(vectp++, (u_int32_t)(intptr_t)destp);
+ while (*stringp++ != 0)
+ destp++;
+ destp++;
+ }
+
+ /* a null vector table pointer separates the argp's from the envp's */
+ suword32(vectp++, 0);
+
+ suword32(&arginfo->ps_envstr, (u_int32_t)(intptr_t)vectp);
+ suword32(&arginfo->ps_nenvstr, envc);
+
+ /*
+ * Fill in environment portion of vector table.
+ */
+ for (; envc > 0; --envc) {
+ suword32(vectp++, (u_int32_t)(intptr_t)destp);
+ while (*stringp++ != 0)
+ destp++;
+ destp++;
+ }
+
+ /* end of vector table is a null pointer */
+ suword32(vectp, 0);
+
+ return ((register_t *)stack_base);
+}
+
+static void
+ia32_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings)
+{
+ struct trapframe *frame = td->td_frame;
+ vm_offset_t gdt, ldt;
+ u_int64_t codesel, datasel, ldtsel;
+ u_int64_t codeseg, dataseg, gdtseg, ldtseg;
+ struct segment_descriptor desc;
+ struct vmspace *vmspace = td->td_proc->p_vmspace;
+
+ /*
+ * Make sure that we restore the entire trapframe after an
+ * execve.
+ */
+ frame->tf_flags &= ~FRAME_SYSCALL;
+
+ bzero(frame->tf_r, sizeof(frame->tf_r));
+ bzero(frame->tf_f, sizeof(frame->tf_f));
+
+ frame->tf_cr_iip = entry;
+ frame->tf_cr_ipsr = (IA64_PSR_IC
+ | IA64_PSR_I
+ | IA64_PSR_IT
+ | IA64_PSR_DT
+ | IA64_PSR_RT
+ | IA64_PSR_DFH
+ | IA64_PSR_IS
+ | IA64_PSR_BN
+ | IA64_PSR_CPL_USER);
+ frame->tf_r[FRAME_R12] = stack;
+
+ codesel = LSEL(LUCODE_SEL, SEL_UPL);
+ datasel = LSEL(LUDATA_SEL, SEL_UPL);
+ ldtsel = GSEL(GLDT_SEL, SEL_UPL);
+
+#if 1
+ frame->tf_r[FRAME_R16] = (datasel << 48) | (datasel << 32)
+ | (datasel << 16) | datasel;
+ frame->tf_r[FRAME_R17] = (ldtsel << 32) | (datasel << 16) | codesel;
+#else
+ frame->tf_r[FRAME_R16] = datasel;
+ frame->tf_r[FRAME_R17] = codesel;
+ frame->tf_r[FRAME_R18] = datasel;
+ frame->tf_r[FRAME_R19] = datasel;
+ frame->tf_r[FRAME_R20] = datasel;
+ frame->tf_r[FRAME_R21] = datasel;
+ frame->tf_r[FRAME_R22] = ldtsel;
+#endif
+
+ /*
+ * Build the GDT and LDT.
+ */
+ gdt = IA32_USRSTACK;
+ vm_map_find(&vmspace->vm_map, 0, 0,
+ &gdt, PAGE_SIZE, 0,
+ VM_PROT_ALL, VM_PROT_ALL, 0);
+ ldt = gdt + 4096;
+
+ desc.sd_lolimit = 8*NLDT-1;
+ desc.sd_lobase = ldt & 0xffffff;
+ desc.sd_type = SDT_SYSLDT;
+ desc.sd_dpl = SEL_UPL;
+ desc.sd_p = 1;
+ desc.sd_hilimit = 0;
+ desc.sd_def32 = 0;
+ desc.sd_gran = 0;
+ desc.sd_hibase = ldt >> 24;
+ copyout(&desc, (caddr_t) gdt + 8*GLDT_SEL, sizeof(desc));
+
+ desc.sd_lolimit = ((IA32_USRSTACK >> 12) - 1) & 0xffff;
+ desc.sd_lobase = 0;
+ desc.sd_type = SDT_MEMERA;
+ desc.sd_dpl = SEL_UPL;
+ desc.sd_p = 1;
+ desc.sd_hilimit = ((IA32_USRSTACK >> 12) - 1) >> 16;
+ desc.sd_def32 = 1;
+ desc.sd_gran = 1;
+ desc.sd_hibase = 0;
+ copyout(&desc, (caddr_t) ldt + 8*LUCODE_SEL, sizeof(desc));
+ desc.sd_type = SDT_MEMRWA;
+ copyout(&desc, (caddr_t) ldt + 8*LUDATA_SEL, sizeof(desc));
+
+ codeseg = 0 /* base */
+ + (((IA32_USRSTACK >> 12) - 1) << 32) /* limit */
+ + ((long)SDT_MEMERA << 52)
+ + ((long)SEL_UPL << 57)
+ + (1L << 59) /* present */
+ + (1L << 62) /* 32 bits */
+ + (1L << 63); /* page granularity */
+ dataseg = 0 /* base */
+ + (((IA32_USRSTACK >> 12) - 1) << 32) /* limit */
+ + ((long)SDT_MEMRWA << 52)
+ + ((long)SEL_UPL << 57)
+ + (1L << 59) /* present */
+ + (1L << 62) /* 32 bits */
+ + (1L << 63); /* page granularity */
+ ia64_set_csd(codeseg);
+ ia64_set_ssd(dataseg);
+ frame->tf_r[FRAME_R24] = dataseg; /* ESD */
+ frame->tf_r[FRAME_R27] = dataseg; /* DSD */
+ frame->tf_r[FRAME_R28] = dataseg; /* FSD */
+ frame->tf_r[FRAME_R29] = dataseg; /* GSD */
+
+ gdtseg = gdt /* base */
+ + ((8L*NGDT - 1) << 32) /* limit */
+ + ((long)SDT_SYSNULL << 52)
+ + ((long)SEL_UPL << 57)
+ + (1L << 59) /* present */
+ + (0L << 62) /* 16 bits */
+ + (0L << 63); /* byte granularity */
+ ldtseg = ldt /* base */
+ + ((8L*NLDT - 1) << 32) /* limit */
+ + ((long)SDT_SYSLDT << 52)
+ + ((long)SEL_UPL << 57)
+ + (1L << 59) /* present */
+ + (0L << 62) /* 16 bits */
+ + (0L << 63); /* byte granularity */
+ frame->tf_r[FRAME_R30] = ldtseg; /* LDTD */
+ frame->tf_r[FRAME_R31] = gdtseg; /* GDTD */
+
+ ia64_set_eflag(PSL_USER);
+
+ /* PS_STRINGS value for BSD/OS binaries. It is 0 for non-BSD/OS. */
+ frame->tf_r[FRAME_R11] = IA32_PS_STRINGS;
+
+ /*
+ * XXX - Linux emulator
+ * Make sure sure edx is 0x0 on entry. Linux binaries depend
+ * on it.
+ */
+ td->td_retval[1] = 0;
+}
diff --git a/sys/compat/ia32/ia32_util.h b/sys/compat/ia32/ia32_util.h
new file mode 100644
index 000000000000..b9e0a7c4d98a
--- /dev/null
+++ b/sys/compat/ia32/ia32_util.h
@@ -0,0 +1,94 @@
+/*-
+ * Copyright (c) 1998-1999 Andrew Gallatin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+
+
+#include <sys/exec.h>
+#include <sys/sysent.h>
+#include <sys/cdefs.h>
+
+
+#ifndef SCARG
+#define SCARG(p, x) (p)->x
+#endif
+
+struct ia32_ps_strings {
+ u_int32_t ps_argvstr; /* first of 0 or more argument strings */
+ int ps_nargvstr; /* the number of argument strings */
+ u_int32_t ps_envstr; /* first of 0 or more environment strings */
+ int ps_nenvstr; /* the number of environment strings */
+};
+
+#define IA32_USRSTACK (4L*1024*1024*1024 - PAGE_SIZE)
+#define IA32_PS_STRINGS (IA32_USRSTACK - sizeof(struct ia32_ps_strings))
+
+static __inline caddr_t stackgap_init(void);
+static __inline void *stackgap_alloc(caddr_t *, size_t);
+
+static __inline caddr_t
+stackgap_init()
+{
+#define szsigcode (*(curproc->p_sysent->sv_szsigcode))
+ return (caddr_t)(((caddr_t)IA32_PS_STRINGS) - szsigcode - SPARE_USRSPACE);
+#undef szsigcode
+}
+
+static __inline void *
+stackgap_alloc(sgp, sz)
+ caddr_t *sgp;
+ size_t sz;
+{
+ void *p;
+
+ p = (void *) *sgp;
+ *sgp += ALIGN(sz);
+ return p;
+}
+
+
+extern const char ia32_emul_path[];
+int ia32_emul_find(struct thread *, caddr_t *, const char *, char *,
+ char **, int);
+
+#define CHECKALT(p, sgp, path, i) \
+ do { \
+ int _error; \
+ \
+ _error = ia32_emul_find(p, sgp, ia32_emul_path, path, \
+ &path, i); \
+ if (_error == EFAULT) \
+ return (_error); \
+ } while (0)
+
+#define CHECKALTEXIST(p, sgp, path) CHECKALT((p), (sgp), (path), 0)
+#define CHECKALTCREAT(p, sgp, path) CHECKALT((p), (sgp), (path), 1)
diff --git a/sys/compat/pecoff/imgact_pecoff.c b/sys/compat/pecoff/imgact_pecoff.c
index 8196aa1c4002..2d4691d4db48 100644
--- a/sys/compat/pecoff/imgact_pecoff.c
+++ b/sys/compat/pecoff/imgact_pecoff.c
@@ -465,7 +465,7 @@ exec_pecoff_coff_prep_zmagic(struct image_params * imgp,
peofs + PECOFF_HDR_SIZE, (caddr_t) sh, scnsiz);
if ((error = exec_extract_strings(imgp)) != 0)
goto fail;
- exec_new_vmspace(imgp);
+ exec_new_vmspace(imgp, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS, USRSTACK);
vmspace = imgp->proc->p_vmspace;
for (i = 0; i < fp->f_nscns; i++) {
prot = VM_PROT_WRITE; /* XXX for relocation? */
diff --git a/sys/compat/svr4/imgact_svr4.c b/sys/compat/svr4/imgact_svr4.c
index 43b71bed3b53..ad72929f4a9d 100644
--- a/sys/compat/svr4/imgact_svr4.c
+++ b/sys/compat/svr4/imgact_svr4.c
@@ -119,7 +119,7 @@ exec_svr4_imgact(imgp)
/*
* Destroy old process VM and create a new one (with a new stack)
*/
- exec_new_vmspace(imgp);
+ exec_new_vmspace(imgp, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS, USRSTACK);
vmspace = imgp->proc->p_vmspace;
/*
diff --git a/sys/compat/svr4/svr4_sysvec.c b/sys/compat/svr4/svr4_sysvec.c
index 1c37adb95437..c7d67ffd78fd 100644
--- a/sys/compat/svr4/svr4_sysvec.c
+++ b/sys/compat/svr4/svr4_sysvec.c
@@ -179,13 +179,14 @@ struct sysentvec svr4_sysvec = {
&svr4_szsigcode,
NULL,
"SVR4",
- elf_coredump,
+ elf32_coredump,
NULL,
SVR4_MINSIGSTKSZ
};
Elf32_Brandinfo svr4_brand = {
ELFOSABI_SYSV,
+ EM_386, /* XXX only implemented for x86 so far. */
"SVR4",
svr4_emul_path,
"/lib/libc.so.1",
@@ -376,7 +377,7 @@ svr4_elf_modevent(module_t mod, int type, void *data)
switch(type) {
case MOD_LOAD:
- if (elf_insert_brand_entry(&svr4_brand) < 0)
+ if (elf32_insert_brand_entry(&svr4_brand) < 0)
error = EINVAL;
if (error)
printf("cannot insert svr4 elf brand handler\n");
@@ -385,9 +386,9 @@ svr4_elf_modevent(module_t mod, int type, void *data)
break;
case MOD_UNLOAD:
/* Only allow the emulator to be removed if it isn't in use. */
- if (elf_brand_inuse(&svr4_brand) != 0) {
+ if (elf32_brand_inuse(&svr4_brand) != 0) {
error = EBUSY;
- } else if (elf_remove_brand_entry(&svr4_brand) < 0) {
+ } else if (elf32_remove_brand_entry(&svr4_brand) < 0) {
error = EINVAL;
}
diff --git a/sys/conf/files b/sys/conf/files
index dfdb9bb0f241..f41c0714e586 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -841,7 +841,9 @@ isofs/cd9660/cd9660_rrip.c optional cd9660
isofs/cd9660/cd9660_util.c optional cd9660
isofs/cd9660/cd9660_vfsops.c optional cd9660
isofs/cd9660/cd9660_vnops.c optional cd9660
-kern/imgact_elf.c standard
+kern/imgact_elf32.c standard
+kern/imgact_elf64.c standard
+kern/imgact_elfN.c standard
kern/imgact_shell.c standard
kern/inflate.c optional gzip
kern/init_main.c standard
diff --git a/sys/conf/files.ia64 b/sys/conf/files.ia64
index c0c120b456bf..292c89424779 100644
--- a/sys/conf/files.ia64
+++ b/sys/conf/files.ia64
@@ -22,8 +22,9 @@ ia64/acpica/acpi_machdep.c optional acpica
ia64/acpica/acpi_wakeup.c optional acpica
ia64/acpica/OsdEnvironment.c optional acpica
ia64/acpica/madt.c optional acpica
+ia64/ia32/ia32_misc.c optional ia32
ia64/ia32/ia32_sysent.c optional ia32
-ia64/ia32/imgact_ia32.c optional ia32
+ia64/ia32/ia32_sysvec.c optional ia32
ia64/ia64/ia64-gdbstub.c optional ddb
ia64/ia64/autoconf.c standard
ia64/ia64/busdma_machdep.c standard
diff --git a/sys/i386/i386/elf_machdep.c b/sys/i386/i386/elf_machdep.c
index 96d91b00c04d..188d60e6529b 100644
--- a/sys/i386/i386/elf_machdep.c
+++ b/sys/i386/i386/elf_machdep.c
@@ -26,9 +26,49 @@
*/
#include <sys/param.h>
+#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/linker.h>
+#include <sys/sysent.h>
+#include <sys/imgact_elf.h>
+#include <sys/syscall.h>
+#include <sys/signalvar.h>
+#include <sys/vnode.h>
#include <machine/elf.h>
+#include <machine/md_var.h>
+
+struct sysentvec elf32_freebsd_sysvec = {
+ SYS_MAXSYSCALL,
+ sysent,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ elf32_freebsd_fixup,
+ sendsig,
+ sigcode,
+ &szsigcode,
+ 0,
+ "FreeBSD ELF32",
+ __elfN(coredump),
+ NULL,
+ MINSIGSTKSZ
+};
+
+static Elf32_Brandinfo freebsd_brand_info = {
+ ELFOSABI_FREEBSD,
+ EM_386,
+ "FreeBSD",
+ "",
+ "/usr/libexec/ld-elf.so.1",
+ &elf32_freebsd_sysvec
+ };
+
+SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_ANY,
+ (sysinit_cfunc_t) elf32_insert_brand_entry,
+ &freebsd_brand_info);
/* Process one elf relocation with addend. */
int
diff --git a/sys/i386/ibcs2/imgact_coff.c b/sys/i386/ibcs2/imgact_coff.c
index 94eb6cf9faf7..0a554d6fd0a1 100644
--- a/sys/i386/ibcs2/imgact_coff.c
+++ b/sys/i386/ibcs2/imgact_coff.c
@@ -333,7 +333,7 @@ exec_coff_imgact(imgp)
return error;
}
- exec_new_vmspace(imgp);
+ exec_new_vmspace(imgp, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS, USRSTACK);
vmspace = imgp->proc->p_vmspace;
for (i = 0; i < nscns; i++) {
diff --git a/sys/i386/linux/imgact_linux.c b/sys/i386/linux/imgact_linux.c
index 3bb42e3a8505..86e249a1894d 100644
--- a/sys/i386/linux/imgact_linux.c
+++ b/sys/i386/linux/imgact_linux.c
@@ -118,7 +118,7 @@ exec_linux_imgact(imgp)
/*
* Destroy old process VM and create a new one (with a new stack)
*/
- exec_new_vmspace(imgp);
+ exec_new_vmspace(imgp, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS, USRSTACK);
vmspace = imgp->proc->p_vmspace;
/*
diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c
index 090b89d53654..a5ebc0a6c2a1 100644
--- a/sys/i386/linux/linux_sysvec.c
+++ b/sys/i386/linux/linux_sysvec.c
@@ -792,13 +792,14 @@ struct sysentvec elf_linux_sysvec = {
&linux_szsigcode,
linux_prepsyscall,
"Linux ELF",
- elf_coredump,
+ elf32_coredump,
exec_linux_imgact_try,
LINUX_MINSIGSTKSZ
};
static Elf32_Brandinfo linux_brand = {
ELFOSABI_LINUX,
+ EM_386,
"Linux",
"/compat/linux",
"/lib/ld-linux.so.1",
@@ -807,6 +808,7 @@ static Elf32_Brandinfo linux_brand = {
static Elf32_Brandinfo linux_glibc2brand = {
ELFOSABI_LINUX,
+ EM_386,
"Linux",
"/compat/linux",
"/lib/ld-linux.so.2",
@@ -832,7 +834,7 @@ linux_elf_modevent(module_t mod, int type, void *data)
case MOD_LOAD:
for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL;
++brandinfo)
- if (elf_insert_brand_entry(*brandinfo) < 0)
+ if (elf32_insert_brand_entry(*brandinfo) < 0)
error = EINVAL;
if (error == 0) {
SET_FOREACH(lihp, linux_ioctl_handler_set)
@@ -845,12 +847,12 @@ linux_elf_modevent(module_t mod, int type, void *data)
case MOD_UNLOAD:
for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL;
++brandinfo)
- if (elf_brand_inuse(*brandinfo))
+ if (elf32_brand_inuse(*brandinfo))
error = EBUSY;
if (error == 0) {
for (brandinfo = &linux_brandlist[0];
*brandinfo != NULL; ++brandinfo)
- if (elf_remove_brand_entry(*brandinfo) < 0)
+ if (elf32_remove_brand_entry(*brandinfo) < 0)
error = EINVAL;
}
if (error == 0) {
diff --git a/sys/ia64/ia32/ia32.h b/sys/ia64/ia32/ia32.h
new file mode 100644
index 000000000000..943b24c61ed3
--- /dev/null
+++ b/sys/ia64/ia32/ia32.h
@@ -0,0 +1,103 @@
+/*-
+ * Copyright (c) 2001 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _IA64_IA32_IA32_H_
+#define _IA64_IA32_IA32_H_
+
+#define PTRIN(v) (void *)(uintptr_t) (v)
+#define PTROUT(v) (u_int32_t)(uintptr_t) (v)
+
+#define CP(src,dst,fld) do { (dst).fld = (src).fld; } while (0)
+#define PTRIN_CP(src,dst,fld) \
+ do { (dst).fld = PTRIN((src).fld); } while (0)
+#define PTROUT_CP(src,dst,fld) \
+ do { (dst).fld = PTROUT((src).fld); } while (0)
+
+struct timeval32 {
+ int32_t tv_sec;
+ int32_t tv_usec;
+};
+#define TV_CP(src,dst,fld) do { \
+ CP((src).fld,(dst).fld,tv_sec); \
+ CP((src).fld,(dst).fld,tv_usec); \
+} while (0);
+
+struct timespec32 {
+ u_int32_t tv_sec;
+ u_int32_t tv_nsec;
+};
+#define TS_CP(src,dst,fld) do { \
+ CP((src).fld,(dst).fld,tv_sec); \
+ CP((src).fld,(dst).fld,tv_nsec); \
+} while (0);
+
+struct rusage32 {
+ struct timeval32 ru_utime;
+ struct timeval32 ru_stime;
+ int32_t ru_maxrss;
+ int32_t ru_ixrss;
+ int32_t ru_idrss;
+ int32_t ru_isrss;
+ int32_t ru_minflt;
+ int32_t ru_majflt;
+ int32_t ru_nswap;
+ int32_t ru_inblock;
+ int32_t ru_oublock;
+ int32_t ru_msgsnd;
+ int32_t ru_msgrcv;
+ int32_t ru_nsignals;
+ int32_t ru_nvcsw;
+ int32_t ru_nivcsw;
+};
+
+struct statfs32 {
+ int32_t f_spare2;
+ int32_t f_bsize;
+ int32_t f_iosize;
+ int32_t f_blocks;
+ int32_t f_bfree;
+ int32_t f_bavail;
+ int32_t f_files;
+ int32_t f_ffree;
+ fsid_t f_fsid;
+ uid_t f_owner;
+ int32_t f_type;
+ int32_t f_flags;
+ int32_t f_syncwrites;
+ int32_t f_asyncwrites;
+ char f_fstypename[MFSNAMELEN];
+ char f_mntonname[MNAMELEN];
+ int32_t f_syncreads;
+ int32_t f_asyncreads;
+ int16_t f_spares1;
+ char f_mntfromname[MNAMELEN];
+ int16_t f_spares2;
+ int32_t f_spare[2];
+};
+
+#endif /* !_IA64_IA32_IA32_H_ */
diff --git a/sys/ia64/ia32/ia32_misc.c b/sys/ia64/ia32/ia32_misc.c
new file mode 100644
index 000000000000..8b28bcee0a52
--- /dev/null
+++ b/sys/ia64/ia32/ia32_misc.c
@@ -0,0 +1,1339 @@
+/*-
+ * Copyright (c) 2002 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/dkstat.h>
+#include <sys/exec.h>
+#include <sys/fcntl.h>
+#include <sys/filedesc.h>
+#include <sys/imgact.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/file.h> /* Must come after sys/malloc.h */
+#include <sys/mman.h>
+#include <sys/module.h>
+#include <sys/mount.h>
+#include <sys/mutex.h>
+#include <sys/namei.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/reboot.h>
+#include <sys/resource.h>
+#include <sys/resourcevar.h>
+#include <sys/selinfo.h>
+#include <sys/pipe.h> /* Must come after sys/selinfo.h */
+#include <sys/signal.h>
+#include <sys/signalvar.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/sysent.h>
+#include <sys/sysproto.h>
+#include <sys/systm.h>
+#include <sys/unistd.h>
+#include <sys/user.h>
+#include <sys/utsname.h>
+#include <sys/vnode.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_extern.h>
+
+#include <ia64/ia32/ia32_util.h>
+#include <ia64/ia32/ia32.h>
+#include <ia64/ia32/ia32_proto.h>
+
+static const char ia32_emul_path[] = "/compat/ia32";
+/*
+ * [ taken from the linux emulator ]
+ * Search an alternate path before passing pathname arguments on
+ * to system calls. Useful for keeping a separate 'emulation tree'.
+ *
+ * If cflag is set, we check if an attempt can be made to create
+ * the named file, i.e. we check if the directory it should
+ * be in exists.
+ */
+int
+ia32_emul_find(td, sgp, prefix, path, pbuf, cflag)
+ struct thread *td;
+ caddr_t *sgp; /* Pointer to stackgap memory */
+ const char *prefix;
+ char *path;
+ char **pbuf;
+ int cflag;
+{
+ int error;
+ size_t len, sz;
+ char *buf, *cp, *ptr;
+ struct ucred *ucred;
+ struct nameidata nd;
+ struct nameidata ndroot;
+ struct vattr vat;
+ struct vattr vatroot;
+
+ buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
+ *pbuf = path;
+
+ for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++)
+ continue;
+
+ sz = MAXPATHLEN - (ptr - buf);
+
+ /*
+ * If sgp is not given then the path is already in kernel space
+ */
+ if (sgp == NULL)
+ error = copystr(path, ptr, sz, &len);
+ else
+ error = copyinstr(path, ptr, sz, &len);
+
+ if (error) {
+ free(buf, M_TEMP);
+ return error;
+ }
+
+ if (*ptr != '/') {
+ free(buf, M_TEMP);
+ return EINVAL;
+ }
+
+ /*
+ * We know that there is a / somewhere in this pathname.
+ * Search backwards for it, to find the file's parent dir
+ * to see if it exists in the alternate tree. If it does,
+ * and we want to create a file (cflag is set). We don't
+ * need to worry about the root comparison in this case.
+ */
+
+ if (cflag) {
+ for (cp = &ptr[len] - 1; *cp != '/'; cp--)
+ ;
+ *cp = '\0';
+
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
+
+ if ((error = namei(&nd)) != 0) {
+ free(buf, M_TEMP);
+ return error;
+ }
+
+ *cp = '/';
+ } else {
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
+
+ if ((error = namei(&nd)) != 0) {
+ free(buf, M_TEMP);
+ return error;
+ }
+
+ /*
+ * We now compare the vnode of the ia32_root to the one
+ * vnode asked. If they resolve to be the same, then we
+ * ignore the match so that the real root gets used.
+ * This avoids the problem of traversing "../.." to find the
+ * root directory and never finding it, because "/" resolves
+ * to the emulation root directory. This is expensive :-(
+ */
+ NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, ia32_emul_path,
+ td);
+
+ if ((error = namei(&ndroot)) != 0) {
+ /* Cannot happen! */
+ free(buf, M_TEMP);
+ vrele(nd.ni_vp);
+ return error;
+ }
+
+ ucred = td->td_ucred;
+ if ((error = VOP_GETATTR(nd.ni_vp, &vat, ucred, td)) != 0) {
+ goto bad;
+ }
+
+ if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, ucred,
+ td)) != 0) {
+ goto bad;
+ }
+
+ if (vat.va_fsid == vatroot.va_fsid &&
+ vat.va_fileid == vatroot.va_fileid) {
+ error = ENOENT;
+ goto bad;
+ }
+
+ }
+ if (sgp == NULL)
+ *pbuf = buf;
+ else {
+ sz = &ptr[len] - buf;
+ *pbuf = stackgap_alloc(sgp, sz + 1);
+ error = copyout(buf, *pbuf, sz);
+ free(buf, M_TEMP);
+ }
+
+ vrele(nd.ni_vp);
+ if (!cflag)
+ vrele(ndroot.ni_vp);
+
+ return error;
+
+bad:
+ vrele(ndroot.ni_vp);
+ vrele(nd.ni_vp);
+ free(buf, M_TEMP);
+ return error;
+}
+
+int
+ia32_open(struct thread *td, struct ia32_open_args *uap)
+{
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, uap->path);
+
+ return open(td, (struct open_args *) uap);
+}
+
+int
+ia32_wait4(struct thread *td, struct ia32_wait4_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct rusage32 *rusage32, ru32;
+ struct rusage *rusage = NULL, ru;
+
+ rusage32 = SCARG(uap, rusage);
+ if (rusage32) {
+ sg = stackgap_init();
+ rusage = stackgap_alloc(&sg, sizeof(struct rusage));
+ SCARG(uap, rusage) = (struct rusage32 *)rusage;
+ }
+ error = wait4(td, (struct wait_args *)uap);
+ if (error)
+ return (error);
+ if (rusage32 && (error = copyin(rusage, &ru, sizeof(ru)) == 0)) {
+ TV_CP(ru, ru32, ru_utime);
+ TV_CP(ru, ru32, ru_stime);
+ CP(ru, ru32, ru_maxrss);
+ CP(ru, ru32, ru_ixrss);
+ CP(ru, ru32, ru_idrss);
+ CP(ru, ru32, ru_isrss);
+ CP(ru, ru32, ru_minflt);
+ CP(ru, ru32, ru_majflt);
+ CP(ru, ru32, ru_nswap);
+ CP(ru, ru32, ru_inblock);
+ CP(ru, ru32, ru_oublock);
+ CP(ru, ru32, ru_msgsnd);
+ CP(ru, ru32, ru_msgrcv);
+ CP(ru, ru32, ru_nsignals);
+ CP(ru, ru32, ru_nvcsw);
+ CP(ru, ru32, ru_nivcsw);
+ error = copyout(&ru32, rusage32, sizeof(ru32));
+ }
+ return (error);
+}
+
+static void
+copy_statfs(struct statfs *in, struct statfs32 *out)
+{
+ CP(*in, *out, f_bsize);
+ CP(*in, *out, f_iosize);
+ CP(*in, *out, f_blocks);
+ CP(*in, *out, f_bfree);
+ CP(*in, *out, f_bavail);
+ CP(*in, *out, f_files);
+ CP(*in, *out, f_ffree);
+ CP(*in, *out, f_fsid);
+ CP(*in, *out, f_owner);
+ CP(*in, *out, f_type);
+ CP(*in, *out, f_flags);
+ CP(*in, *out, f_flags);
+ CP(*in, *out, f_syncwrites);
+ CP(*in, *out, f_asyncwrites);
+ bcopy(in->f_fstypename,
+ out->f_fstypename, MFSNAMELEN);
+ bcopy(in->f_mntonname,
+ out->f_mntonname, MNAMELEN);
+ CP(*in, *out, f_syncreads);
+ CP(*in, *out, f_asyncreads);
+ bcopy(in->f_mntfromname,
+ out->f_mntfromname, MNAMELEN);
+}
+
+int
+ia32_getfsstat(struct thread *td, struct ia32_getfsstat_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct statfs32 *sp32, stat32;
+ struct statfs *sp = NULL, stat;
+ int maxcount, count, i;
+
+ sp32 = SCARG(uap, buf);
+ maxcount = SCARG(uap, bufsize) / sizeof(struct statfs32);
+
+ if (sp32) {
+ sg = stackgap_init();
+ sp = stackgap_alloc(&sg, sizeof(struct statfs) * maxcount);
+ SCARG(uap, buf) = (struct statfs32 *)sp;
+ }
+ error = getfsstat(td, (struct getfsstat_args *) uap);
+ if (sp32 && !error) {
+ count = td->td_retval[0];
+ for (i = 0; i < count; i++) {
+ error = copyin(&sp[i], &stat, sizeof(stat));
+ if (error)
+ return (error);
+ copy_statfs(&stat, &stat32);
+ error = copyout(&stat32, &sp32[i], sizeof(stat32));
+ if (error)
+ return (error);
+ }
+ }
+ return (error);
+}
+
+int
+ia32_access(struct thread *td, struct ia32_access_args *uap)
+{
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, uap->path);
+
+ return access(td, (struct access_args *)uap);
+}
+
+int
+ia32_chflags(struct thread *td, struct ia32_chflags_args *uap)
+{
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, uap->path);
+
+ return chflags(td, (struct chflags_args *)uap);
+}
+
+struct sigaltstack32 {
+ u_int32_t ss_sp;
+ u_int32_t ss_size;
+ int ss_flags;
+};
+
+int
+ia32_sigaltstack(struct thread *td, struct ia32_sigaltstack_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct sigaltstack32 *p32, *op32, s32;
+ struct sigaltstack *p = NULL, *op = NULL, s;
+
+ p32 = SCARG(uap, ss);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct sigaltstack));
+ SCARG(uap, ss) = (struct sigaltstack32 *)p;
+ error = copyin(p32, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ PTRIN_CP(s32, s, ss_sp);
+ CP(s32, s, ss_size);
+ CP(s32, s, ss_flags);
+ error = copyout(&s, p, sizeof(s));
+ if (error)
+ return (error);
+ }
+ op32 = SCARG(uap, oss);
+ if (op32) {
+ sg = stackgap_init();
+ op = stackgap_alloc(&sg, sizeof(struct sigaltstack));
+ SCARG(uap, oss) = (struct sigaltstack32 *)op;
+ }
+ error = sigaltstack(td, (struct sigaltstack_args *) uap);
+ if (error)
+ return (error);
+ if (op32) {
+ error = copyin(op, &s, sizeof(s));
+ if (error)
+ return (error);
+ PTROUT_CP(s, s32, ss_sp);
+ CP(s, s32, ss_size);
+ CP(s, s32, ss_flags);
+ error = copyout(&s32, op32, sizeof(s32));
+ }
+ return (error);
+}
+
+int
+ia32_execve(struct thread *td, struct ia32_execve_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct execve_args ap;
+ u_int32_t *p32, arg;
+ char **p;
+ int count;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, SCARG(uap, fname));
+ SCARG(&ap, fname) = SCARG(uap, fname);
+
+ if (SCARG(uap, argv)) {
+ count = 0;
+ p32 = SCARG(uap, argv);
+ do {
+ error = copyin(p32++, &arg, sizeof(arg));
+ if (error)
+ return error;
+ count++;
+ } while (arg != 0);
+ p = stackgap_alloc(&sg, count * sizeof(char *));
+ SCARG(&ap, argv) = p;
+ p32 = SCARG(uap, argv);
+ do {
+ error = copyin(p32++, &arg, sizeof(arg));
+ if (error)
+ return error;
+ *p++ = PTRIN(arg);
+ } while (arg != 0);
+ }
+ if (SCARG(uap, envv)) {
+ count = 0;
+ p32 = SCARG(uap, envv);
+ do {
+ error = copyin(p32++, &arg, sizeof(arg));
+ if (error)
+ return error;
+ count++;
+ } while (arg != 0);
+ p = stackgap_alloc(&sg, count * sizeof(char *));
+ SCARG(&ap, envv) = p;
+ p32 = SCARG(uap, envv);
+ do {
+ error = copyin(p32++, &arg, sizeof(arg));
+ if (error)
+ return error;
+ *p++ = PTRIN(arg);
+ } while (arg != 0);
+ }
+
+ return execve(td, &ap);
+}
+
+static int
+ia32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
+ int prot, int fd, off_t pos)
+{
+ vm_map_t map;
+ vm_map_entry_t entry;
+ int rv;
+
+ map = &td->td_proc->p_vmspace->vm_map;
+ if (fd != -1)
+ prot |= VM_PROT_WRITE;
+
+ if (vm_map_lookup_entry(map, start, &entry)) {
+ if ((entry->protection & prot) != prot) {
+ rv = vm_map_protect(map,
+ trunc_page(start),
+ round_page(end),
+ entry->protection | prot,
+ FALSE);
+ if (rv != KERN_SUCCESS)
+ return (EINVAL);
+ }
+ } else {
+ vm_offset_t addr = trunc_page(start);
+ rv = vm_map_find(map, 0, 0,
+ &addr, PAGE_SIZE, FALSE, prot,
+ VM_PROT_ALL, 0);
+ if (rv != KERN_SUCCESS)
+ return (EINVAL);
+ }
+
+ if (fd != -1) {
+ struct pread_args r;
+ SCARG(&r, fd) = fd;
+ SCARG(&r, buf) = (void *) start;
+ SCARG(&r, nbyte) = end - start;
+ SCARG(&r, offset) = pos;
+ return (pread(td, &r));
+ } else {
+ while (start < end) {
+ subyte((void *) start, 0);
+ start++;
+ }
+ return (0);
+ }
+}
+
+int
+ia32_mmap(struct thread *td, struct ia32_mmap_args *uap)
+{
+ struct mmap_args ap;
+ vm_offset_t addr = (vm_offset_t) SCARG(uap, addr);
+ vm_size_t len = SCARG(uap, len);
+ int prot = SCARG(uap, prot);
+ int flags = SCARG(uap, flags);
+ int fd = SCARG(uap, fd);
+ off_t pos = (SCARG(uap, poslo)
+ | ((off_t)SCARG(uap, poshi) << 32));
+ vm_size_t pageoff;
+ int error;
+
+ /*
+ * Attempt to handle page size hassles.
+ */
+ pageoff = (pos & PAGE_MASK);
+ if (flags & MAP_FIXED) {
+ vm_offset_t start, end;
+ start = addr;
+ end = addr + len;
+
+ if (start != trunc_page(start)) {
+ error = ia32_mmap_partial(td, start, round_page(start),
+ prot, fd, pos);
+ if (fd != -1)
+ pos += round_page(start) - start;
+ start = round_page(start);
+ }
+ if (end != round_page(end)) {
+ vm_offset_t t = trunc_page(end);
+ error = ia32_mmap_partial(td, t, end,
+ prot, fd,
+ pos + t - start);
+ end = trunc_page(end);
+ }
+ if (end > start && fd != -1 && (pos & PAGE_MASK)) {
+ /*
+ * We can't map this region at all. The specified
+ * address doesn't have the same alignment as the file
+ * position. Fake the mapping by simply reading the
+ * entire region into memory. First we need to make
+ * sure the region exists.
+ */
+ vm_map_t map;
+ struct pread_args r;
+ int rv;
+
+ prot |= VM_PROT_WRITE;
+ map = &td->td_proc->p_vmspace->vm_map;
+ rv = vm_map_remove(map, start, end);
+ if (rv != KERN_SUCCESS)
+ return (EINVAL);
+ rv = vm_map_find(map, 0, 0,
+ &start, end - start, FALSE,
+ prot, VM_PROT_ALL, 0);
+ if (rv != KERN_SUCCESS)
+ return (EINVAL);
+ SCARG(&r, fd) = fd;
+ SCARG(&r, buf) = (void *) start;
+ SCARG(&r, nbyte) = end - start;
+ SCARG(&r, offset) = pos;
+ error = pread(td, &r);
+ if (error)
+ return (error);
+
+ td->td_retval[0] = addr;
+ return (0);
+ }
+ if (end == start) {
+ /*
+ * After dealing with the ragged ends, there
+ * might be none left.
+ */
+ td->td_retval[0] = addr;
+ return (0);
+ }
+ addr = start;
+ len = end - start;
+ }
+
+ SCARG(&ap, addr) = (void *) addr;
+ SCARG(&ap, len) = len;
+ SCARG(&ap, prot) = prot;
+ SCARG(&ap, flags) = flags;
+ SCARG(&ap, fd) = fd;
+ SCARG(&ap, pos) = pos;
+
+ return (mmap(td, &ap));
+}
+
+struct itimerval32 {
+ struct timeval32 it_interval;
+ struct timeval32 it_value;
+};
+
+int
+ia32_setitimer(struct thread *td, struct ia32_setitimer_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct itimerval32 *p32, *op32, s32;
+ struct itimerval *p = NULL, *op = NULL, s;
+
+ p32 = SCARG(uap, itv);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct itimerval));
+ SCARG(uap, itv) = (struct itimerval32 *)p;
+ error = copyin(p32, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ TV_CP(s32, s, it_interval);
+ TV_CP(s32, s, it_value);
+ error = copyout(&s, p, sizeof(s));
+ if (error)
+ return (error);
+ }
+ op32 = SCARG(uap, oitv);
+ if (op32) {
+ sg = stackgap_init();
+ op = stackgap_alloc(&sg, sizeof(struct itimerval));
+ SCARG(uap, oitv) = (struct itimerval32 *)op;
+ }
+ error = setitimer(td, (struct setitimer_args *) uap);
+ if (error)
+ return (error);
+ if (op32) {
+ error = copyin(op, &s, sizeof(s));
+ if (error)
+ return (error);
+ TV_CP(s, s32, it_interval);
+ TV_CP(s, s32, it_value);
+ error = copyout(&s32, op32, sizeof(s32));
+ }
+ return (error);
+}
+
+int
+ia32_select(struct thread *td, struct ia32_select_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct timeval32 *p32, s32;
+ struct timeval *p = NULL, s;
+
+ p32 = SCARG(uap, tv);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct timeval));
+ SCARG(uap, tv) = (struct timeval32 *)p;
+ error = copyin(p32, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ CP(s32, s, tv_sec);
+ CP(s32, s, tv_usec);
+ error = copyout(&s, p, sizeof(s));
+ if (error)
+ return (error);
+ }
+ /*
+ * XXX big-endian needs to convert the fd_sets too.
+ */
+ return (select(td, (struct select_args *) uap));
+}
+
+int
+ia32_gettimeofday(struct thread *td, struct ia32_gettimeofday_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct timeval32 *p32, s32;
+ struct timeval *p = NULL, s;
+
+ p32 = SCARG(uap, tp);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct timeval));
+ SCARG(uap, tp) = (struct timeval32 *)p;
+ }
+ error = gettimeofday(td, (struct gettimeofday_args *) uap);
+ if (error)
+ return (error);
+ if (p32) {
+ error = copyin(p, &s, sizeof(s));
+ if (error)
+ return (error);
+ CP(s, s32, tv_sec);
+ CP(s, s32, tv_usec);
+ error = copyout(&s32, p32, sizeof(s32));
+ if (error)
+ return (error);
+ }
+ return (error);
+}
+
+int
+ia32_getrusage(struct thread *td, struct ia32_getrusage_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct rusage32 *p32, s32;
+ struct rusage *p = NULL, s;
+
+ p32 = SCARG(uap, rusage);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct rusage));
+ SCARG(uap, rusage) = (struct rusage32 *)p;
+ }
+ error = getrusage(td, (struct getrusage_args *) uap);
+ if (error)
+ return (error);
+ if (p32) {
+ error = copyin(p, &s, sizeof(s));
+ if (error)
+ return (error);
+ TV_CP(s, s32, ru_utime);
+ TV_CP(s, s32, ru_stime);
+ CP(s, s32, ru_maxrss);
+ CP(s, s32, ru_ixrss);
+ CP(s, s32, ru_idrss);
+ CP(s, s32, ru_isrss);
+ CP(s, s32, ru_minflt);
+ CP(s, s32, ru_majflt);
+ CP(s, s32, ru_nswap);
+ CP(s, s32, ru_inblock);
+ CP(s, s32, ru_oublock);
+ CP(s, s32, ru_msgsnd);
+ CP(s, s32, ru_msgrcv);
+ CP(s, s32, ru_nsignals);
+ CP(s, s32, ru_nvcsw);
+ CP(s, s32, ru_nivcsw);
+ error = copyout(&s32, p32, sizeof(s32));
+ }
+ return (error);
+}
+
+struct iovec32 {
+ u_int32_t iov_base;
+ int iov_len;
+};
+#define STACKGAPLEN 400
+
+int
+ia32_readv(struct thread *td, struct ia32_readv_args *uap)
+{
+ int error, osize, nsize, i;
+ caddr_t sg;
+ struct readv_args /* {
+ syscallarg(int) fd;
+ syscallarg(struct iovec *) iovp;
+ syscallarg(u_int) iovcnt;
+ } */ a;
+ struct iovec32 *oio;
+ struct iovec *nio;
+
+ sg = stackgap_init();
+
+ if (SCARG(uap, iovcnt) > (STACKGAPLEN / sizeof (struct iovec)))
+ return (EINVAL);
+
+ osize = SCARG(uap, iovcnt) * sizeof (struct iovec32);
+ nsize = SCARG(uap, iovcnt) * sizeof (struct iovec);
+
+ oio = malloc(osize, M_TEMP, M_WAITOK);
+ nio = malloc(nsize, M_TEMP, M_WAITOK);
+
+ error = 0;
+ if ((error = copyin(SCARG(uap, iovp), oio, osize)))
+ goto punt;
+ for (i = 0; i < SCARG(uap, iovcnt); i++) {
+ nio[i].iov_base = PTRIN(oio[i].iov_base);
+ nio[i].iov_len = oio[i].iov_len;
+ }
+
+ SCARG(&a, fd) = SCARG(uap, fd);
+ SCARG(&a, iovp) = stackgap_alloc(&sg, nsize);
+ SCARG(&a, iovcnt) = SCARG(uap, iovcnt);
+
+ if ((error = copyout(nio, (caddr_t)SCARG(&a, iovp), nsize)))
+ goto punt;
+ error = readv(td, &a);
+
+punt:
+ free(oio, M_TEMP);
+ free(nio, M_TEMP);
+ return (error);
+}
+
+int
+ia32_writev(struct thread *td, struct ia32_writev_args *uap)
+{
+ int error, i, nsize, osize;
+ caddr_t sg;
+ struct writev_args /* {
+ syscallarg(int) fd;
+ syscallarg(struct iovec *) iovp;
+ syscallarg(u_int) iovcnt;
+ } */ a;
+ struct iovec32 *oio;
+ struct iovec *nio;
+
+ sg = stackgap_init();
+
+ if (SCARG(uap, iovcnt) > (STACKGAPLEN / sizeof (struct iovec)))
+ return (EINVAL);
+
+ osize = SCARG(uap, iovcnt) * sizeof (struct iovec32);
+ nsize = SCARG(uap, iovcnt) * sizeof (struct iovec);
+
+ oio = malloc(osize, M_TEMP, M_WAITOK);
+ nio = malloc(nsize, M_TEMP, M_WAITOK);
+
+ error = 0;
+ if ((error = copyin(SCARG(uap, iovp), oio, osize)))
+ goto punt;
+ for (i = 0; i < SCARG(uap, iovcnt); i++) {
+ nio[i].iov_base = PTRIN(oio[i].iov_base);
+ nio[i].iov_len = oio[i].iov_len;
+ }
+
+ SCARG(&a, fd) = SCARG(uap, fd);
+ SCARG(&a, iovp) = stackgap_alloc(&sg, nsize);
+ SCARG(&a, iovcnt) = SCARG(uap, iovcnt);
+
+ if ((error = copyout(nio, (caddr_t)SCARG(&a, iovp), nsize)))
+ goto punt;
+ error = writev(td, &a);
+
+punt:
+ free(oio, M_TEMP);
+ free(nio, M_TEMP);
+ return (error);
+}
+
+int
+ia32_settimeofday(struct thread *td, struct ia32_settimeofday_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct timeval32 *p32, s32;
+ struct timeval *p = NULL, s;
+
+ p32 = SCARG(uap, tv);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct timeval));
+ SCARG(uap, tv) = (struct timeval32 *)p;
+ error = copyin(p32, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ CP(s32, s, tv_sec);
+ CP(s32, s, tv_usec);
+ error = copyout(&s, p, sizeof(s));
+ if (error)
+ return (error);
+ }
+ return (settimeofday(td, (struct settimeofday_args *) uap));
+}
+
+int
+ia32_utimes(struct thread *td, struct ia32_utimes_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct timeval32 *p32, s32[2];
+ struct timeval *p = NULL, s[2];
+
+ p32 = SCARG(uap, tptr);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, 2*sizeof(struct timeval));
+ SCARG(uap, tptr) = (struct timeval32 *)p;
+ error = copyin(p32, s32, sizeof(s32));
+ if (error)
+ return (error);
+ CP(s32[0], s[0], tv_sec);
+ CP(s32[0], s[0], tv_usec);
+ CP(s32[1], s[1], tv_sec);
+ CP(s32[1], s[1], tv_usec);
+ error = copyout(s, p, sizeof(s));
+ if (error)
+ return (error);
+ }
+ return (utimes(td, (struct utimes_args *) uap));
+}
+
+int
+ia32_adjtime(struct thread *td, struct ia32_adjtime_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct timeval32 *p32, *op32, s32;
+ struct timeval *p = NULL, *op = NULL, s;
+
+ p32 = SCARG(uap, delta);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct timeval));
+ SCARG(uap, delta) = (struct timeval32 *)p;
+ error = copyin(p32, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ CP(s32, s, tv_sec);
+ CP(s32, s, tv_usec);
+ error = copyout(&s, p, sizeof(s));
+ if (error)
+ return (error);
+ }
+ op32 = SCARG(uap, olddelta);
+ if (op32) {
+ sg = stackgap_init();
+ op = stackgap_alloc(&sg, sizeof(struct timeval));
+ SCARG(uap, olddelta) = (struct timeval32 *)op;
+ }
+ error = utimes(td, (struct utimes_args *) uap);
+ if (error)
+ return error;
+ if (op32) {
+ error = copyin(op, &s, sizeof(s));
+ if (error)
+ return (error);
+ CP(s, s32, tv_sec);
+ CP(s, s32, tv_usec);
+ error = copyout(&s32, op32, sizeof(s32));
+ }
+ return (error);
+}
+
+int
+ia32_statfs(struct thread *td, struct ia32_statfs_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct statfs32 *p32, s32;
+ struct statfs *p = NULL, s;
+
+ p32 = SCARG(uap, buf);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct statfs));
+ SCARG(uap, buf) = (struct statfs32 *)p;
+ }
+ error = statfs(td, (struct statfs_args *) uap);
+ if (error)
+ return (error);
+ if (p32) {
+ error = copyin(p, &s, sizeof(s));
+ if (error)
+ return (error);
+ copy_statfs(&s, &s32);
+ error = copyout(&s32, p32, sizeof(s32));
+ }
+ return (error);
+}
+
+int
+ia32_fstatfs(struct thread *td, struct ia32_fstatfs_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct statfs32 *p32, s32;
+ struct statfs *p = NULL, s;
+
+ p32 = SCARG(uap, buf);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct statfs));
+ SCARG(uap, buf) = (struct statfs32 *)p;
+ }
+ error = fstatfs(td, (struct fstatfs_args *) uap);
+ if (error)
+ return (error);
+ if (p32) {
+ error = copyin(p, &s, sizeof(s));
+ if (error)
+ return (error);
+ copy_statfs(&s, &s32);
+ error = copyout(&s32, p32, sizeof(s32));
+ }
+ return (error);
+}
+
+int
+ia32_semsys(struct thread *td, struct ia32_semsys_args *uap)
+{
+ /*
+ * Vector through to semsys if it is loaded.
+ */
+ return sysent[169].sy_call(td, uap);
+}
+
+int
+ia32_msgsys(struct thread *td, struct ia32_msgsys_args *uap)
+{
+ /*
+ * Vector through to msgsys if it is loaded.
+ */
+ return sysent[170].sy_call(td, uap);
+}
+
+int
+ia32_shmsys(struct thread *td, struct ia32_shmsys_args *uap)
+{
+ /*
+ * Vector through to shmsys if it is loaded.
+ */
+ return sysent[171].sy_call(td, uap);
+}
+
+int
+ia32_pread(struct thread *td, struct ia32_pread_args *uap)
+{
+ struct pread_args ap;
+
+ SCARG(&ap, fd) = SCARG(uap, fd);
+ SCARG(&ap, buf) = SCARG(uap, buf);
+ SCARG(&ap, nbyte) = SCARG(uap, nbyte);
+ SCARG(&ap, offset) = (SCARG(uap, offsetlo)
+ | ((off_t)SCARG(uap, offsethi) << 32));
+ return (pread(td, &ap));
+}
+
+int
+ia32_pwrite(struct thread *td, struct ia32_pwrite_args *uap)
+{
+ struct pwrite_args ap;
+
+ SCARG(&ap, fd) = SCARG(uap, fd);
+ SCARG(&ap, buf) = SCARG(uap, buf);
+ SCARG(&ap, nbyte) = SCARG(uap, nbyte);
+ SCARG(&ap, offset) = (SCARG(uap, offsetlo)
+ | ((off_t)SCARG(uap, offsethi) << 32));
+ return (pwrite(td, &ap));
+}
+
+int
+ia32_lseek(struct thread *td, struct ia32_lseek_args *uap)
+{
+ int error;
+ struct lseek_args ap;
+ off_t pos;
+
+ SCARG(&ap, fd) = SCARG(uap, fd);
+ SCARG(&ap, offset) = (SCARG(uap, offsetlo)
+ | ((off_t)SCARG(uap, offsethi) << 32));
+ SCARG(&ap, whence) = SCARG(uap, whence);
+ error = lseek(td, &ap);
+ /* Expand the quad return into two parts for eax and edx */
+ pos = *(off_t *)(td->td_retval);
+ td->td_retval[0] = pos & 0xffffffff; /* %eax */
+ td->td_retval[1] = pos >> 32; /* %edx */
+ return error;
+}
+
+int
+ia32_truncate(struct thread *td, struct ia32_truncate_args *uap)
+{
+ struct truncate_args ap;
+
+ SCARG(&ap, path) = SCARG(uap, path);
+ SCARG(&ap, length) = (SCARG(uap, lengthlo)
+ | ((off_t)SCARG(uap, lengthhi) << 32));
+ return (truncate(td, &ap));
+}
+
+int
+ia32_ftruncate(struct thread *td, struct ia32_ftruncate_args *uap)
+{
+ struct ftruncate_args ap;
+
+ SCARG(&ap, fd) = SCARG(uap, fd);
+ SCARG(&ap, length) = (SCARG(uap, lengthlo)
+ | ((off_t)SCARG(uap, lengthhi) << 32));
+ return (ftruncate(td, &ap));
+}
+
+int
+ia32_sendfile(struct thread *td, struct ia32_sendfile_args *uap)
+{
+ struct sendfile_args ap;
+
+ SCARG(&ap, fd) = SCARG(uap, fd);
+ SCARG(&ap, s) = SCARG(uap, s);
+ SCARG(&ap, offset) = (SCARG(uap, offsetlo)
+ | ((off_t)SCARG(uap, offsethi) << 32));
+ SCARG(&ap, nbytes) = SCARG(uap, nbytes); /* XXX check */
+ SCARG(&ap, hdtr) = SCARG(uap, hdtr); /* XXX check */
+ SCARG(&ap, sbytes) = SCARG(uap, sbytes); /* XXX FIXME!! */
+ SCARG(&ap, flags) = SCARG(uap, flags);
+ return (sendfile(td, &ap));
+}
+
+struct stat32 {
+ udev_t st_dev;
+ ino_t st_ino;
+ mode_t st_mode;
+ nlink_t st_nlink;
+ uid_t st_uid;
+ gid_t st_gid;
+ udev_t st_rdev;
+ struct timespec32 st_atimespec;
+ struct timespec32 st_mtimespec;
+ struct timespec32 st_ctimespec;
+ off_t st_size;
+ int64_t st_blocks;
+ u_int32_t st_blksize;
+ u_int32_t st_flags;
+ u_int32_t st_gen;
+};
+
+static void
+copy_stat( struct stat *in, struct stat32 *out)
+{
+ CP(*in, *out, st_dev);
+ CP(*in, *out, st_ino);
+ CP(*in, *out, st_mode);
+ CP(*in, *out, st_nlink);
+ CP(*in, *out, st_uid);
+ CP(*in, *out, st_gid);
+ CP(*in, *out, st_rdev);
+ TS_CP(*in, *out, st_atimespec);
+ TS_CP(*in, *out, st_mtimespec);
+ TS_CP(*in, *out, st_ctimespec);
+ CP(*in, *out, st_size);
+ CP(*in, *out, st_blocks);
+ CP(*in, *out, st_blksize);
+ CP(*in, *out, st_flags);
+ CP(*in, *out, st_gen);
+}
+
+int
+ia32_stat(struct thread *td, struct ia32_stat_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct stat32 *p32, s32;
+ struct stat *p = NULL, s;
+
+ p32 = SCARG(uap, ub);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct stat));
+ SCARG(uap, ub) = (struct stat32 *)p;
+ }
+ error = stat(td, (struct stat_args *) uap);
+ if (error)
+ return (error);
+ if (p32) {
+ error = copyin(p, &s, sizeof(s));
+ if (error)
+ return (error);
+ copy_stat(&s, &s32);
+ error = copyout(&s32, p32, sizeof(s32));
+ }
+ return (error);
+}
+
+int
+ia32_fstat(struct thread *td, struct ia32_fstat_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct stat32 *p32, s32;
+ struct stat *p = NULL, s;
+
+ p32 = SCARG(uap, ub);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct stat));
+ SCARG(uap, ub) = (struct stat32 *)p;
+ }
+ error = fstat(td, (struct fstat_args *) uap);
+ if (error)
+ return (error);
+ if (p32) {
+ error = copyin(p, &s, sizeof(s));
+ if (error)
+ return (error);
+ copy_stat(&s, &s32);
+ error = copyout(&s32, p32, sizeof(s32));
+ }
+ return (error);
+}
+
+int
+ia32_lstat(struct thread *td, struct ia32_lstat_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct stat32 *p32, s32;
+ struct stat *p = NULL, s;
+
+ p32 = SCARG(uap, ub);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct stat));
+ SCARG(uap, ub) = (struct stat32 *)p;
+ }
+ error = lstat(td, (struct lstat_args *) uap);
+ if (error)
+ return (error);
+ if (p32) {
+ error = copyin(p, &s, sizeof(s));
+ if (error)
+ return (error);
+ copy_stat(&s, &s32);
+ error = copyout(&s32, p32, sizeof(s32));
+ }
+ return (error);
+}
+
+/*
+ * MPSAFE
+ */
+int
+ia32_sysctl(struct thread *td, struct ia32_sysctl_args *uap)
+{
+ int error, name[CTL_MAXNAME];
+ size_t j, oldlen;
+
+ if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
+ return (EINVAL);
+
+ error = copyin(uap->name, &name, uap->namelen * sizeof(int));
+ if (error)
+ return (error);
+
+ mtx_lock(&Giant);
+
+ if (uap->oldlenp)
+ oldlen = fuword32(uap->oldlenp);
+ else
+ oldlen = 0;
+ error = userland_sysctl(td, name, uap->namelen,
+ uap->old, &oldlen, 1,
+ uap->new, uap->newlen, &j);
+ if (error && error != ENOMEM)
+ goto done2;
+ if (uap->oldlenp) {
+ suword32(uap->oldlenp, j);
+ }
+done2:
+ mtx_unlock(&Giant);
+ return (error);
+}
+
+struct sigaction32 {
+ u_int32_t sa_u;
+ int sa_flags;
+ sigset_t sa_mask;
+};
+
+int
+ia32_sigaction(struct thread *td, struct ia32_sigaction_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct sigaction32 *p32, *op32, s32;
+ struct sigaction *p = NULL, *op = NULL, s;
+
+ p32 = SCARG(uap, act);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct sigaction));
+ SCARG(uap, act) = (struct sigaction32 *)p;
+ error = copyin(p32, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ s.sa_handler = PTRIN(s32.sa_u);
+ CP(s32, s, sa_flags);
+ CP(s32, s, sa_mask);
+ error = copyout(&s, p, sizeof(s));
+ if (error)
+ return (error);
+ }
+ op32 = SCARG(uap, oact);
+ if (op32) {
+ sg = stackgap_init();
+ op = stackgap_alloc(&sg, sizeof(struct sigaction));
+ SCARG(uap, oact) = (struct sigaction32 *)op;
+ }
+ error = sigaction(td, (struct sigaction_args *) uap);
+ if (error)
+ return (error);
+ if (op32) {
+ error = copyin(op, &s, sizeof(s));
+ if (error)
+ return (error);
+ s32.sa_u = PTROUT(s.sa_handler);
+ CP(s, s32, sa_flags);
+ CP(s, s32, sa_mask);
+ error = copyout(&s32, op32, sizeof(s32));
+ }
+ return (error);
+}
+
+#if 0
+
+int
+ia32_xxx(struct thread *td, struct ia32_xxx_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct yyy32 *p32, s32;
+ struct yyy *p = NULL, s;
+
+ p32 = SCARG(uap, zzz);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct yyy));
+ SCARG(uap, zzz) = (struct yyy32 *)p;
+ error = copyin(p32, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ /* translate in */
+ error = copyout(&s, p, sizeof(s));
+ if (error)
+ return (error);
+ }
+ error = xxx(td, (struct xxx_args *) uap);
+ if (error)
+ return (error);
+ if (p32) {
+ error = copyin(p, &s, sizeof(s));
+ if (error)
+ return (error);
+ /* translate out */
+ error = copyout(&s32, p32, sizeof(s32));
+ }
+ return (error);
+}
+
+#endif
diff --git a/sys/ia64/ia32/ia32_signal.c b/sys/ia64/ia32/ia32_signal.c
new file mode 100644
index 000000000000..06e6505a4b3e
--- /dev/null
+++ b/sys/ia64/ia32/ia32_signal.c
@@ -0,0 +1,365 @@
+/*-
+ * Copyright (c) 2002 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#define __ELF_WORD_SIZE 32
+
+#include <sys/param.h>
+#include <sys/exec.h>
+#include <sys/fcntl.h>
+#include <sys/imgact.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/mman.h>
+#include <sys/namei.h>
+#include <sys/pioctl.h>
+#include <sys/proc.h>
+#include <sys/procfs.h>
+#include <sys/resourcevar.h>
+#include <sys/systm.h>
+#include <sys/signalvar.h>
+#include <sys/stat.h>
+#include <sys/sx.h>
+#include <sys/syscall.h>
+#include <sys/sysctl.h>
+#include <sys/sysent.h>
+#include <sys/vnode.h>
+#include <sys/imgact_elf.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_extern.h>
+
+#include <ia64/ia32/ia32_util.h>
+#include <i386/include/psl.h>
+#include <i386/include/segments.h>
+#include <i386/include/specialreg.h>
+#include <machine/frame.h>
+#include <machine/md_var.h>
+
+static register_t *ia32_copyout_strings(struct image_params *imgp);
+static void ia32_setregs(struct thread *td, u_long entry, u_long stack,
+ u_long ps_strings);
+
+extern struct sysent ia32_sysent[];
+
+static char ia32_sigcode[] = {
+ 0xff, 0x54, 0x24, 0x10, /* call *SIGF_HANDLER(%esp) */
+ 0x8d, 0x44, 0x24, 0x14, /* lea SIGF_UC(%esp),%eax */
+ 0x50, /* pushl %eax */
+ 0xf7, 0x40, 0x54, 0x00, 0x00, 0x02, 0x02, /* testl $PSL_VM,UC_EFLAGS(%eax) */
+ 0x75, 0x03, /* jne 9f */
+ 0x8e, 0x68, 0x14, /* movl UC_GS(%eax),%gs */
+ 0xb8, 0x57, 0x01, 0x00, 0x00, /* 9: movl $SYS_sigreturn,%eax */
+ 0x50, /* pushl %eax */
+ 0xcd, 0x80, /* int $0x80 */
+ 0xeb, 0xfe, /* 0: jmp 0b */
+ 0, 0, 0, 0
+};
+static int ia32_szsigcode = sizeof(ia32_sigcode) & ~3;
+
+struct sysentvec ia32_freebsd_sysvec = {
+ SYS_MAXSYSCALL,
+ ia32_sysent,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ elf32_freebsd_fixup,
+ sendsig,
+ ia32_sigcode,
+ &ia32_szsigcode,
+ 0,
+ "FreeBSD ELF",
+ elf32_coredump,
+ NULL,
+ MINSIGSTKSZ,
+ 4096,
+ IA32_USRSTACK,
+ IA32_USRSTACK,
+ ia32_copyout_strings,
+ ia32_setregs
+};
+
+static Elf32_Brandinfo ia32_brand_info = {
+ ELFOSABI_FREEBSD,
+ EM_386,
+ "FreeBSD",
+ "/compat/ia32",
+ "/usr/libexec/ld-elf.so.1",
+ &ia32_freebsd_sysvec
+ };
+
+SYSINIT(ia32, SI_SUB_EXEC, SI_ORDER_ANY,
+ (sysinit_cfunc_t) elf32_insert_brand_entry,
+ &ia32_brand_info);
+
+static register_t *
+ia32_copyout_strings(struct image_params *imgp)
+{
+ int argc, envc;
+ u_int32_t *vectp;
+ char *stringp, *destp;
+ u_int32_t *stack_base;
+ struct ia32_ps_strings *arginfo;
+ int szsigcode;
+
+ /*
+ * Calculate string base and vector table pointers.
+ * Also deal with signal trampoline code for this exec type.
+ */
+ arginfo = (struct ia32_ps_strings *)IA32_PS_STRINGS;
+ szsigcode = *(imgp->proc->p_sysent->sv_szsigcode);
+ destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE -
+ roundup((ARG_MAX - imgp->stringspace), sizeof(char *));
+
+ /*
+ * install sigcode
+ */
+ if (szsigcode)
+ copyout(imgp->proc->p_sysent->sv_sigcode,
+ ((caddr_t)arginfo - szsigcode), szsigcode);
+
+ /*
+ * If we have a valid auxargs ptr, prepare some room
+ * on the stack.
+ */
+ if (imgp->auxargs) {
+ /*
+ * 'AT_COUNT*2' is size for the ELF Auxargs data. This is for
+ * lower compatibility.
+ */
+ imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size
+ : (AT_COUNT * 2);
+ /*
+ * The '+ 2' is for the null pointers at the end of each of
+ * the arg and env vector sets,and imgp->auxarg_size is room
+ * for argument of Runtime loader.
+ */
+ vectp = (u_int32_t *) (destp - (imgp->argc + imgp->envc + 2 +
+ imgp->auxarg_size) * sizeof(u_int32_t));
+
+ } else
+ /*
+ * The '+ 2' is for the null pointers at the end of each of
+ * the arg and env vector sets
+ */
+ vectp = (u_int32_t *)
+ (destp - (imgp->argc + imgp->envc + 2) * sizeof(u_int32_t));
+
+ /*
+ * vectp also becomes our initial stack base
+ */
+ stack_base = vectp;
+
+ stringp = imgp->stringbase;
+ argc = imgp->argc;
+ envc = imgp->envc;
+
+ /*
+ * Copy out strings - arguments and environment.
+ */
+ copyout(stringp, destp, ARG_MAX - imgp->stringspace);
+
+ /*
+ * Fill in "ps_strings" struct for ps, w, etc.
+ */
+ suword32(&arginfo->ps_argvstr, (u_int32_t)(intptr_t)vectp);
+ suword32(&arginfo->ps_nargvstr, argc);
+
+ /*
+ * Fill in argument portion of vector table.
+ */
+ for (; argc > 0; --argc) {
+ suword32(vectp++, (u_int32_t)(intptr_t)destp);
+ while (*stringp++ != 0)
+ destp++;
+ destp++;
+ }
+
+ /* a null vector table pointer separates the argp's from the envp's */
+ suword32(vectp++, 0);
+
+ suword32(&arginfo->ps_envstr, (u_int32_t)(intptr_t)vectp);
+ suword32(&arginfo->ps_nenvstr, envc);
+
+ /*
+ * Fill in environment portion of vector table.
+ */
+ for (; envc > 0; --envc) {
+ suword32(vectp++, (u_int32_t)(intptr_t)destp);
+ while (*stringp++ != 0)
+ destp++;
+ destp++;
+ }
+
+ /* end of vector table is a null pointer */
+ suword32(vectp, 0);
+
+ return ((register_t *)stack_base);
+}
+
+static void
+ia32_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings)
+{
+ struct trapframe *frame = td->td_frame;
+ vm_offset_t gdt, ldt;
+ u_int64_t codesel, datasel, ldtsel;
+ u_int64_t codeseg, dataseg, gdtseg, ldtseg;
+ struct segment_descriptor desc;
+ struct vmspace *vmspace = td->td_proc->p_vmspace;
+
+ /*
+ * Make sure that we restore the entire trapframe after an
+ * execve.
+ */
+ frame->tf_flags &= ~FRAME_SYSCALL;
+
+ bzero(frame->tf_r, sizeof(frame->tf_r));
+ bzero(frame->tf_f, sizeof(frame->tf_f));
+
+ frame->tf_cr_iip = entry;
+ frame->tf_cr_ipsr = (IA64_PSR_IC
+ | IA64_PSR_I
+ | IA64_PSR_IT
+ | IA64_PSR_DT
+ | IA64_PSR_RT
+ | IA64_PSR_DFH
+ | IA64_PSR_IS
+ | IA64_PSR_BN
+ | IA64_PSR_CPL_USER);
+ frame->tf_r[FRAME_R12] = stack;
+
+ codesel = LSEL(LUCODE_SEL, SEL_UPL);
+ datasel = LSEL(LUDATA_SEL, SEL_UPL);
+ ldtsel = GSEL(GLDT_SEL, SEL_UPL);
+
+#if 1
+ frame->tf_r[FRAME_R16] = (datasel << 48) | (datasel << 32)
+ | (datasel << 16) | datasel;
+ frame->tf_r[FRAME_R17] = (ldtsel << 32) | (datasel << 16) | codesel;
+#else
+ frame->tf_r[FRAME_R16] = datasel;
+ frame->tf_r[FRAME_R17] = codesel;
+ frame->tf_r[FRAME_R18] = datasel;
+ frame->tf_r[FRAME_R19] = datasel;
+ frame->tf_r[FRAME_R20] = datasel;
+ frame->tf_r[FRAME_R21] = datasel;
+ frame->tf_r[FRAME_R22] = ldtsel;
+#endif
+
+ /*
+ * Build the GDT and LDT.
+ */
+ gdt = IA32_USRSTACK;
+ vm_map_find(&vmspace->vm_map, 0, 0,
+ &gdt, PAGE_SIZE, 0,
+ VM_PROT_ALL, VM_PROT_ALL, 0);
+ ldt = gdt + 4096;
+
+ desc.sd_lolimit = 8*NLDT-1;
+ desc.sd_lobase = ldt & 0xffffff;
+ desc.sd_type = SDT_SYSLDT;
+ desc.sd_dpl = SEL_UPL;
+ desc.sd_p = 1;
+ desc.sd_hilimit = 0;
+ desc.sd_def32 = 0;
+ desc.sd_gran = 0;
+ desc.sd_hibase = ldt >> 24;
+ copyout(&desc, (caddr_t) gdt + 8*GLDT_SEL, sizeof(desc));
+
+ desc.sd_lolimit = ((IA32_USRSTACK >> 12) - 1) & 0xffff;
+ desc.sd_lobase = 0;
+ desc.sd_type = SDT_MEMERA;
+ desc.sd_dpl = SEL_UPL;
+ desc.sd_p = 1;
+ desc.sd_hilimit = ((IA32_USRSTACK >> 12) - 1) >> 16;
+ desc.sd_def32 = 1;
+ desc.sd_gran = 1;
+ desc.sd_hibase = 0;
+ copyout(&desc, (caddr_t) ldt + 8*LUCODE_SEL, sizeof(desc));
+ desc.sd_type = SDT_MEMRWA;
+ copyout(&desc, (caddr_t) ldt + 8*LUDATA_SEL, sizeof(desc));
+
+ codeseg = 0 /* base */
+ + (((IA32_USRSTACK >> 12) - 1) << 32) /* limit */
+ + ((long)SDT_MEMERA << 52)
+ + ((long)SEL_UPL << 57)
+ + (1L << 59) /* present */
+ + (1L << 62) /* 32 bits */
+ + (1L << 63); /* page granularity */
+ dataseg = 0 /* base */
+ + (((IA32_USRSTACK >> 12) - 1) << 32) /* limit */
+ + ((long)SDT_MEMRWA << 52)
+ + ((long)SEL_UPL << 57)
+ + (1L << 59) /* present */
+ + (1L << 62) /* 32 bits */
+ + (1L << 63); /* page granularity */
+ ia64_set_csd(codeseg);
+ ia64_set_ssd(dataseg);
+ frame->tf_r[FRAME_R24] = dataseg; /* ESD */
+ frame->tf_r[FRAME_R27] = dataseg; /* DSD */
+ frame->tf_r[FRAME_R28] = dataseg; /* FSD */
+ frame->tf_r[FRAME_R29] = dataseg; /* GSD */
+
+ gdtseg = gdt /* base */
+ + ((8L*NGDT - 1) << 32) /* limit */
+ + ((long)SDT_SYSNULL << 52)
+ + ((long)SEL_UPL << 57)
+ + (1L << 59) /* present */
+ + (0L << 62) /* 16 bits */
+ + (0L << 63); /* byte granularity */
+ ldtseg = ldt /* base */
+ + ((8L*NLDT - 1) << 32) /* limit */
+ + ((long)SDT_SYSLDT << 52)
+ + ((long)SEL_UPL << 57)
+ + (1L << 59) /* present */
+ + (0L << 62) /* 16 bits */
+ + (0L << 63); /* byte granularity */
+ frame->tf_r[FRAME_R30] = ldtseg; /* LDTD */
+ frame->tf_r[FRAME_R31] = gdtseg; /* GDTD */
+
+ ia64_set_eflag(PSL_USER);
+
+ /* PS_STRINGS value for BSD/OS binaries. It is 0 for non-BSD/OS. */
+ frame->tf_r[FRAME_R11] = IA32_PS_STRINGS;
+
+ /*
+ * XXX - Linux emulator
+ * Make sure sure edx is 0x0 on entry. Linux binaries depend
+ * on it.
+ */
+ td->td_retval[1] = 0;
+}
diff --git a/sys/ia64/ia32/ia32_sysvec.c b/sys/ia64/ia32/ia32_sysvec.c
new file mode 100644
index 000000000000..06e6505a4b3e
--- /dev/null
+++ b/sys/ia64/ia32/ia32_sysvec.c
@@ -0,0 +1,365 @@
+/*-
+ * Copyright (c) 2002 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#define __ELF_WORD_SIZE 32
+
+#include <sys/param.h>
+#include <sys/exec.h>
+#include <sys/fcntl.h>
+#include <sys/imgact.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/mman.h>
+#include <sys/namei.h>
+#include <sys/pioctl.h>
+#include <sys/proc.h>
+#include <sys/procfs.h>
+#include <sys/resourcevar.h>
+#include <sys/systm.h>
+#include <sys/signalvar.h>
+#include <sys/stat.h>
+#include <sys/sx.h>
+#include <sys/syscall.h>
+#include <sys/sysctl.h>
+#include <sys/sysent.h>
+#include <sys/vnode.h>
+#include <sys/imgact_elf.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_extern.h>
+
+#include <ia64/ia32/ia32_util.h>
+#include <i386/include/psl.h>
+#include <i386/include/segments.h>
+#include <i386/include/specialreg.h>
+#include <machine/frame.h>
+#include <machine/md_var.h>
+
+static register_t *ia32_copyout_strings(struct image_params *imgp);
+static void ia32_setregs(struct thread *td, u_long entry, u_long stack,
+ u_long ps_strings);
+
+extern struct sysent ia32_sysent[];
+
+static char ia32_sigcode[] = {
+ 0xff, 0x54, 0x24, 0x10, /* call *SIGF_HANDLER(%esp) */
+ 0x8d, 0x44, 0x24, 0x14, /* lea SIGF_UC(%esp),%eax */
+ 0x50, /* pushl %eax */
+ 0xf7, 0x40, 0x54, 0x00, 0x00, 0x02, 0x02, /* testl $PSL_VM,UC_EFLAGS(%eax) */
+ 0x75, 0x03, /* jne 9f */
+ 0x8e, 0x68, 0x14, /* movl UC_GS(%eax),%gs */
+ 0xb8, 0x57, 0x01, 0x00, 0x00, /* 9: movl $SYS_sigreturn,%eax */
+ 0x50, /* pushl %eax */
+ 0xcd, 0x80, /* int $0x80 */
+ 0xeb, 0xfe, /* 0: jmp 0b */
+ 0, 0, 0, 0
+};
+static int ia32_szsigcode = sizeof(ia32_sigcode) & ~3;
+
+struct sysentvec ia32_freebsd_sysvec = {
+ SYS_MAXSYSCALL,
+ ia32_sysent,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ elf32_freebsd_fixup,
+ sendsig,
+ ia32_sigcode,
+ &ia32_szsigcode,
+ 0,
+ "FreeBSD ELF",
+ elf32_coredump,
+ NULL,
+ MINSIGSTKSZ,
+ 4096,
+ IA32_USRSTACK,
+ IA32_USRSTACK,
+ ia32_copyout_strings,
+ ia32_setregs
+};
+
+static Elf32_Brandinfo ia32_brand_info = {
+ ELFOSABI_FREEBSD,
+ EM_386,
+ "FreeBSD",
+ "/compat/ia32",
+ "/usr/libexec/ld-elf.so.1",
+ &ia32_freebsd_sysvec
+ };
+
+SYSINIT(ia32, SI_SUB_EXEC, SI_ORDER_ANY,
+ (sysinit_cfunc_t) elf32_insert_brand_entry,
+ &ia32_brand_info);
+
+static register_t *
+ia32_copyout_strings(struct image_params *imgp)
+{
+ int argc, envc;
+ u_int32_t *vectp;
+ char *stringp, *destp;
+ u_int32_t *stack_base;
+ struct ia32_ps_strings *arginfo;
+ int szsigcode;
+
+ /*
+ * Calculate string base and vector table pointers.
+ * Also deal with signal trampoline code for this exec type.
+ */
+ arginfo = (struct ia32_ps_strings *)IA32_PS_STRINGS;
+ szsigcode = *(imgp->proc->p_sysent->sv_szsigcode);
+ destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE -
+ roundup((ARG_MAX - imgp->stringspace), sizeof(char *));
+
+ /*
+ * install sigcode
+ */
+ if (szsigcode)
+ copyout(imgp->proc->p_sysent->sv_sigcode,
+ ((caddr_t)arginfo - szsigcode), szsigcode);
+
+ /*
+ * If we have a valid auxargs ptr, prepare some room
+ * on the stack.
+ */
+ if (imgp->auxargs) {
+ /*
+ * 'AT_COUNT*2' is size for the ELF Auxargs data. This is for
+ * lower compatibility.
+ */
+ imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size
+ : (AT_COUNT * 2);
+ /*
+ * The '+ 2' is for the null pointers at the end of each of
+ * the arg and env vector sets,and imgp->auxarg_size is room
+ * for argument of Runtime loader.
+ */
+ vectp = (u_int32_t *) (destp - (imgp->argc + imgp->envc + 2 +
+ imgp->auxarg_size) * sizeof(u_int32_t));
+
+ } else
+ /*
+ * The '+ 2' is for the null pointers at the end of each of
+ * the arg and env vector sets
+ */
+ vectp = (u_int32_t *)
+ (destp - (imgp->argc + imgp->envc + 2) * sizeof(u_int32_t));
+
+ /*
+ * vectp also becomes our initial stack base
+ */
+ stack_base = vectp;
+
+ stringp = imgp->stringbase;
+ argc = imgp->argc;
+ envc = imgp->envc;
+
+ /*
+ * Copy out strings - arguments and environment.
+ */
+ copyout(stringp, destp, ARG_MAX - imgp->stringspace);
+
+ /*
+ * Fill in "ps_strings" struct for ps, w, etc.
+ */
+ suword32(&arginfo->ps_argvstr, (u_int32_t)(intptr_t)vectp);
+ suword32(&arginfo->ps_nargvstr, argc);
+
+ /*
+ * Fill in argument portion of vector table.
+ */
+ for (; argc > 0; --argc) {
+ suword32(vectp++, (u_int32_t)(intptr_t)destp);
+ while (*stringp++ != 0)
+ destp++;
+ destp++;
+ }
+
+ /* a null vector table pointer separates the argp's from the envp's */
+ suword32(vectp++, 0);
+
+ suword32(&arginfo->ps_envstr, (u_int32_t)(intptr_t)vectp);
+ suword32(&arginfo->ps_nenvstr, envc);
+
+ /*
+ * Fill in environment portion of vector table.
+ */
+ for (; envc > 0; --envc) {
+ suword32(vectp++, (u_int32_t)(intptr_t)destp);
+ while (*stringp++ != 0)
+ destp++;
+ destp++;
+ }
+
+ /* end of vector table is a null pointer */
+ suword32(vectp, 0);
+
+ return ((register_t *)stack_base);
+}
+
+static void
+ia32_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings)
+{
+ struct trapframe *frame = td->td_frame;
+ vm_offset_t gdt, ldt;
+ u_int64_t codesel, datasel, ldtsel;
+ u_int64_t codeseg, dataseg, gdtseg, ldtseg;
+ struct segment_descriptor desc;
+ struct vmspace *vmspace = td->td_proc->p_vmspace;
+
+ /*
+ * Make sure that we restore the entire trapframe after an
+ * execve.
+ */
+ frame->tf_flags &= ~FRAME_SYSCALL;
+
+ bzero(frame->tf_r, sizeof(frame->tf_r));
+ bzero(frame->tf_f, sizeof(frame->tf_f));
+
+ frame->tf_cr_iip = entry;
+ frame->tf_cr_ipsr = (IA64_PSR_IC
+ | IA64_PSR_I
+ | IA64_PSR_IT
+ | IA64_PSR_DT
+ | IA64_PSR_RT
+ | IA64_PSR_DFH
+ | IA64_PSR_IS
+ | IA64_PSR_BN
+ | IA64_PSR_CPL_USER);
+ frame->tf_r[FRAME_R12] = stack;
+
+ codesel = LSEL(LUCODE_SEL, SEL_UPL);
+ datasel = LSEL(LUDATA_SEL, SEL_UPL);
+ ldtsel = GSEL(GLDT_SEL, SEL_UPL);
+
+#if 1
+ frame->tf_r[FRAME_R16] = (datasel << 48) | (datasel << 32)
+ | (datasel << 16) | datasel;
+ frame->tf_r[FRAME_R17] = (ldtsel << 32) | (datasel << 16) | codesel;
+#else
+ frame->tf_r[FRAME_R16] = datasel;
+ frame->tf_r[FRAME_R17] = codesel;
+ frame->tf_r[FRAME_R18] = datasel;
+ frame->tf_r[FRAME_R19] = datasel;
+ frame->tf_r[FRAME_R20] = datasel;
+ frame->tf_r[FRAME_R21] = datasel;
+ frame->tf_r[FRAME_R22] = ldtsel;
+#endif
+
+ /*
+ * Build the GDT and LDT.
+ */
+ gdt = IA32_USRSTACK;
+ vm_map_find(&vmspace->vm_map, 0, 0,
+ &gdt, PAGE_SIZE, 0,
+ VM_PROT_ALL, VM_PROT_ALL, 0);
+ ldt = gdt + 4096;
+
+ desc.sd_lolimit = 8*NLDT-1;
+ desc.sd_lobase = ldt & 0xffffff;
+ desc.sd_type = SDT_SYSLDT;
+ desc.sd_dpl = SEL_UPL;
+ desc.sd_p = 1;
+ desc.sd_hilimit = 0;
+ desc.sd_def32 = 0;
+ desc.sd_gran = 0;
+ desc.sd_hibase = ldt >> 24;
+ copyout(&desc, (caddr_t) gdt + 8*GLDT_SEL, sizeof(desc));
+
+ desc.sd_lolimit = ((IA32_USRSTACK >> 12) - 1) & 0xffff;
+ desc.sd_lobase = 0;
+ desc.sd_type = SDT_MEMERA;
+ desc.sd_dpl = SEL_UPL;
+ desc.sd_p = 1;
+ desc.sd_hilimit = ((IA32_USRSTACK >> 12) - 1) >> 16;
+ desc.sd_def32 = 1;
+ desc.sd_gran = 1;
+ desc.sd_hibase = 0;
+ copyout(&desc, (caddr_t) ldt + 8*LUCODE_SEL, sizeof(desc));
+ desc.sd_type = SDT_MEMRWA;
+ copyout(&desc, (caddr_t) ldt + 8*LUDATA_SEL, sizeof(desc));
+
+ codeseg = 0 /* base */
+ + (((IA32_USRSTACK >> 12) - 1) << 32) /* limit */
+ + ((long)SDT_MEMERA << 52)
+ + ((long)SEL_UPL << 57)
+ + (1L << 59) /* present */
+ + (1L << 62) /* 32 bits */
+ + (1L << 63); /* page granularity */
+ dataseg = 0 /* base */
+ + (((IA32_USRSTACK >> 12) - 1) << 32) /* limit */
+ + ((long)SDT_MEMRWA << 52)
+ + ((long)SEL_UPL << 57)
+ + (1L << 59) /* present */
+ + (1L << 62) /* 32 bits */
+ + (1L << 63); /* page granularity */
+ ia64_set_csd(codeseg);
+ ia64_set_ssd(dataseg);
+ frame->tf_r[FRAME_R24] = dataseg; /* ESD */
+ frame->tf_r[FRAME_R27] = dataseg; /* DSD */
+ frame->tf_r[FRAME_R28] = dataseg; /* FSD */
+ frame->tf_r[FRAME_R29] = dataseg; /* GSD */
+
+ gdtseg = gdt /* base */
+ + ((8L*NGDT - 1) << 32) /* limit */
+ + ((long)SDT_SYSNULL << 52)
+ + ((long)SEL_UPL << 57)
+ + (1L << 59) /* present */
+ + (0L << 62) /* 16 bits */
+ + (0L << 63); /* byte granularity */
+ ldtseg = ldt /* base */
+ + ((8L*NLDT - 1) << 32) /* limit */
+ + ((long)SDT_SYSLDT << 52)
+ + ((long)SEL_UPL << 57)
+ + (1L << 59) /* present */
+ + (0L << 62) /* 16 bits */
+ + (0L << 63); /* byte granularity */
+ frame->tf_r[FRAME_R30] = ldtseg; /* LDTD */
+ frame->tf_r[FRAME_R31] = gdtseg; /* GDTD */
+
+ ia64_set_eflag(PSL_USER);
+
+ /* PS_STRINGS value for BSD/OS binaries. It is 0 for non-BSD/OS. */
+ frame->tf_r[FRAME_R11] = IA32_PS_STRINGS;
+
+ /*
+ * XXX - Linux emulator
+ * Make sure sure edx is 0x0 on entry. Linux binaries depend
+ * on it.
+ */
+ td->td_retval[1] = 0;
+}
diff --git a/sys/ia64/ia32/ia32_util.h b/sys/ia64/ia32/ia32_util.h
new file mode 100644
index 000000000000..b9e0a7c4d98a
--- /dev/null
+++ b/sys/ia64/ia32/ia32_util.h
@@ -0,0 +1,94 @@
+/*-
+ * Copyright (c) 1998-1999 Andrew Gallatin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+
+
+#include <sys/exec.h>
+#include <sys/sysent.h>
+#include <sys/cdefs.h>
+
+
+#ifndef SCARG
+#define SCARG(p, x) (p)->x
+#endif
+
+struct ia32_ps_strings {
+ u_int32_t ps_argvstr; /* first of 0 or more argument strings */
+ int ps_nargvstr; /* the number of argument strings */
+ u_int32_t ps_envstr; /* first of 0 or more environment strings */
+ int ps_nenvstr; /* the number of environment strings */
+};
+
+#define IA32_USRSTACK (4L*1024*1024*1024 - PAGE_SIZE)
+#define IA32_PS_STRINGS (IA32_USRSTACK - sizeof(struct ia32_ps_strings))
+
+static __inline caddr_t stackgap_init(void);
+static __inline void *stackgap_alloc(caddr_t *, size_t);
+
+static __inline caddr_t
+stackgap_init()
+{
+#define szsigcode (*(curproc->p_sysent->sv_szsigcode))
+ return (caddr_t)(((caddr_t)IA32_PS_STRINGS) - szsigcode - SPARE_USRSPACE);
+#undef szsigcode
+}
+
+static __inline void *
+stackgap_alloc(sgp, sz)
+ caddr_t *sgp;
+ size_t sz;
+{
+ void *p;
+
+ p = (void *) *sgp;
+ *sgp += ALIGN(sz);
+ return p;
+}
+
+
+extern const char ia32_emul_path[];
+int ia32_emul_find(struct thread *, caddr_t *, const char *, char *,
+ char **, int);
+
+#define CHECKALT(p, sgp, path, i) \
+ do { \
+ int _error; \
+ \
+ _error = ia32_emul_find(p, sgp, ia32_emul_path, path, \
+ &path, i); \
+ if (_error == EFAULT) \
+ return (_error); \
+ } while (0)
+
+#define CHECKALTEXIST(p, sgp, path) CHECKALT((p), (sgp), (path), 0)
+#define CHECKALTCREAT(p, sgp, path) CHECKALT((p), (sgp), (path), 1)
diff --git a/sys/ia64/ia32/imgact_ia32.c b/sys/ia64/ia32/imgact_ia32.c
deleted file mode 100644
index 3230e6af9738..000000000000
--- a/sys/ia64/ia32/imgact_ia32.c
+++ /dev/null
@@ -1,1446 +0,0 @@
-/*-
- * Copyright (c) 2000 David O'Brien
- * Copyright (c) 1995-1996 Søren Schmidt
- * Copyright (c) 1996 Peter Wemm
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer
- * in this position and unchanged.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-#include <sys/exec.h>
-#include <sys/fcntl.h>
-#include <sys/imgact.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mutex.h>
-#include <sys/mman.h>
-#include <sys/namei.h>
-#include <sys/pioctl.h>
-#include <sys/proc.h>
-#include <sys/procfs.h>
-#include <sys/resourcevar.h>
-#include <sys/systm.h>
-#include <sys/signalvar.h>
-#include <sys/stat.h>
-#include <sys/sx.h>
-#include <sys/syscall.h>
-#include <sys/sysctl.h>
-#include <sys/sysent.h>
-#include <sys/vnode.h>
-
-#include <vm/vm.h>
-#include <vm/vm_kern.h>
-#include <vm/vm_param.h>
-#include <vm/pmap.h>
-#include <vm/vm_map.h>
-#include <vm/vm_object.h>
-#include <vm/vm_extern.h>
-
-#include <ia64/ia32/imgact_ia32.h>
-#include <i386/include/psl.h>
-#include <i386/include/segments.h>
-#include <i386/include/specialreg.h>
-#include <machine/md_var.h>
-
-#define OLD_EI_BRAND 8
-
-__ElfType(Brandinfo);
-__ElfType(Auxargs);
-
-#define IA32_USRSTACK (3L*1024*1024*1024)
-#define IA32_PS_STRINGS (IA32_USRSTACK - sizeof(struct ia32_ps_strings))
-
-static int elf32_check_header(const Elf32_Ehdr *hdr);
-static int elf32_freebsd_fixup(register_t **stack_base,
- struct image_params *imgp);
-static int elf32_load_file(struct proc *p, const char *file, u_long *addr,
- u_long *entry);
-static int elf32_load_section(struct proc *p,
- struct vmspace *vmspace, struct vnode *vp,
- vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz,
- vm_prot_t prot);
-static int exec_elf32_imgact(struct image_params *imgp);
-static int elf32_coredump(struct thread *td, struct vnode *vp, off_t limit);
-static register_t *elf32_copyout_strings(struct image_params *imgp);
-static void elf32_setregs(struct thread *td, u_long entry, u_long stack,
- u_long ps_strings);
-
-static int elf32_trace = 0;
-SYSCTL_INT(_debug, OID_AUTO, elf32_trace, CTLFLAG_RW, &elf32_trace, 0, "");
-
-extern struct sysent ia32_sysent[];
-
-static char ia32_sigcode[] = {
- 0xff, 0x54, 0x24, 0x10, /* call *SIGF_HANDLER(%esp) */
- 0x8d, 0x44, 0x24, 0x14, /* lea SIGF_UC(%esp),%eax */
- 0x50, /* pushl %eax */
- 0xf7, 0x40, 0x54, 0x00, 0x00, 0x02, 0x02, /* testl $PSL_VM,UC_EFLAGS(%eax) */
- 0x75, 0x03, /* jne 9f */
- 0x8e, 0x68, 0x14, /* movl UC_GS(%eax),%gs */
- 0xb8, 0x57, 0x01, 0x00, 0x00, /* 9: movl $SYS_sigreturn,%eax */
- 0x50, /* pushl %eax */
- 0xcd, 0x80, /* int $0x80 */
- 0xeb, 0xfe, /* 0: jmp 0b */
- 0, 0, 0, 0
-};
-static int ia32_szsigcode = sizeof(ia32_sigcode) & ~3;
-
-struct sysentvec elf32_freebsd_sysvec = {
- SYS_MAXSYSCALL,
- ia32_sysent,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- elf32_freebsd_fixup,
- sendsig,
- ia32_sigcode,
- &ia32_szsigcode,
- 0,
- "FreeBSD ELF",
- elf32_coredump,
- NULL,
- MINSIGSTKSZ,
- elf32_copyout_strings,
- elf32_setregs
-};
-
-static Elf32_Brandinfo freebsd_brand_info = {
- ELFOSABI_FREEBSD,
- "FreeBSD",
- "",
- "/usr/libexec/ld-elf.so.1",
- &elf32_freebsd_sysvec
- };
-static Elf32_Brandinfo *elf32_brand_list[MAX_BRANDS] = {
- &freebsd_brand_info,
- NULL, NULL, NULL,
- NULL, NULL, NULL, NULL
- };
-
-#if 0
-
-int
-elf32_insert_brand_entry(Elf32_Brandinfo *entry)
-{
- int i;
-
- for (i=1; i<MAX_BRANDS; i++) {
- if (elf32_brand_list[i] == NULL) {
- elf32_brand_list[i] = entry;
- break;
- }
- }
- if (i == MAX_BRANDS)
- return -1;
- return 0;
-}
-
-int
-elf32_remove_brand_entry(Elf32_Brandinfo *entry)
-{
- int i;
-
- for (i=1; i<MAX_BRANDS; i++) {
- if (elf32_brand_list[i] == entry) {
- elf32_brand_list[i] = NULL;
- break;
- }
- }
- if (i == MAX_BRANDS)
- return -1;
- return 0;
-}
-
-int
-elf32_brand_inuse(Elf32_Brandinfo *entry)
-{
- struct proc *p;
- int rval = FALSE;
-
- sx_slock(&allproc_lock);
- LIST_FOREACH(p, &allproc, p_list) {
- if (p->p_sysent == entry->sysvec) {
- rval = TRUE;
- break;
- }
- }
- sx_sunlock(&allproc_lock);
-
- return (rval);
-}
-
-#endif
-
-static int
-elf32_check_header(const Elf32_Ehdr *hdr)
-{
- if (!IS_ELF(*hdr) ||
- hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS ||
- hdr->e_ident[EI_DATA] != ELF_TARG_DATA ||
- hdr->e_ident[EI_VERSION] != EV_CURRENT)
- return ENOEXEC;
-
- if (!ELF_MACHINE_OK(hdr->e_machine))
- return ENOEXEC;
-
- if (hdr->e_version != ELF_TARG_VER)
- return ENOEXEC;
-
- return 0;
-}
-
-#define PAGE4K_SHIFT 12
-#define PAGE4K_MASK ((1 << PAGE4K_SHIFT)-1)
-#define round_page4k(x) (((x) + PAGE4K_MASK) & ~(PAGE4K_MASK))
-#define trunc_page4k(x) ((x) & ~(PAGE4K_MASK))
-
-static int
-elf32_map_partial(vm_map_t map, vm_object_t object, vm_ooffset_t offset,
- vm_offset_t start, vm_offset_t end, vm_prot_t prot,
- vm_prot_t max)
-{
- int error, rv;
- vm_offset_t off;
- vm_offset_t data_buf = 0;
-
- /*
- * Create the page if it doesn't exist yet. Ignore errors.
- */
- vm_map_lock(map);
- vm_map_insert(map, NULL, 0, trunc_page(start), round_page(end),
- max, max, 0);
- vm_map_unlock(map);
-
- /*
- * Find the page from the underlying object.
- */
- if (object) {
- vm_object_reference(object);
- rv = vm_map_find(exec_map,
- object,
- trunc_page(offset),
- &data_buf,
- PAGE_SIZE,
- TRUE,
- VM_PROT_READ,
- VM_PROT_ALL,
- MAP_COPY_ON_WRITE | MAP_PREFAULT_PARTIAL);
- if (rv != KERN_SUCCESS) {
- vm_object_deallocate(object);
- return rv;
- }
-
- off = offset - trunc_page(offset);
- error = copyout((caddr_t)data_buf+off, (caddr_t)start, end - start);
- vm_map_remove(exec_map, data_buf, data_buf + PAGE_SIZE);
- if (error) {
- return KERN_FAILURE;
- }
- }
-
- return KERN_SUCCESS;
-}
-
-static int
-elf32_map_insert(vm_map_t map, vm_object_t object, vm_ooffset_t offset,
- vm_offset_t start, vm_offset_t end, vm_prot_t prot,
- vm_prot_t max, int cow)
-{
- int rv;
-
- if (start != trunc_page(start)) {
- rv = elf32_map_partial(map, object, offset,
- start, round_page(start), prot, max);
- if (rv)
- return rv;
- start = round_page(start);
- offset = round_page(offset);
- }
- if (end != round_page(end)) {
- rv = elf32_map_partial(map, object, offset,
- trunc_page(end), end, prot, max);
- if (rv)
- return rv;
- end = trunc_page(end);
- }
- if (end > start) {
- vm_map_lock(map);
- rv = vm_map_insert(map, object, offset, start, end,
- prot, max, cow);
- vm_map_unlock(map);
- return rv;
- } else {
- return KERN_SUCCESS;
- }
-}
-
-static int
-elf32_load_section(struct proc *p, struct vmspace *vmspace, struct vnode *vp, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot)
-{
- size_t map_len;
- vm_offset_t map_addr;
- int error, rv;
- size_t copy_len;
- vm_object_t object;
- vm_offset_t file_addr;
- vm_offset_t data_buf = 0;
-
- GIANT_REQUIRED;
-
- VOP_GETVOBJECT(vp, &object);
- error = 0;
-
- /*
- * It's necessary to fail if the filsz + offset taken from the
- * header is greater than the actual file pager object's size.
- * If we were to allow this, then the vm_map_find() below would
- * walk right off the end of the file object and into the ether.
- *
- * While I'm here, might as well check for something else that
- * is invalid: filsz cannot be greater than memsz.
- */
- if ((off_t)filsz + offset > object->un_pager.vnp.vnp_size ||
- filsz > memsz) {
- uprintf("elf32_load_section: truncated ELF file\n");
- return (ENOEXEC);
- }
-
- map_addr = trunc_page4k((vm_offset_t)vmaddr);
- file_addr = trunc_page4k(offset);
-
- /*
- * We have two choices. We can either clear the data in the last page
- * of an oversized mapping, or we can start the anon mapping a page
- * early and copy the initialized data into that first page. We
- * choose the second..
- */
- if (memsz > filsz)
- map_len = trunc_page4k(offset+filsz) - file_addr;
- else
- map_len = round_page4k(offset+filsz) - file_addr;
-
- if (map_len != 0) {
- vm_object_reference(object);
- rv = elf32_map_insert(&vmspace->vm_map,
- object,
- file_addr, /* file offset */
- map_addr, /* virtual start */
- map_addr + map_len,/* virtual end */
- prot,
- VM_PROT_ALL,
- MAP_COPY_ON_WRITE | MAP_PREFAULT);
- if (rv != KERN_SUCCESS) {
- vm_object_deallocate(object);
- return EINVAL;
- }
-
- /* we can stop now if we've covered it all */
- if (memsz == filsz) {
- return 0;
- }
- }
-
-
- /*
- * We have to get the remaining bit of the file into the first part
- * of the oversized map segment. This is normally because the .data
- * segment in the file is extended to provide bss. It's a neat idea
- * to try and save a page, but it's a pain in the behind to implement.
- */
- copy_len = (offset + filsz) - trunc_page4k(offset + filsz);
- map_addr = trunc_page4k((vm_offset_t)vmaddr + filsz);
- map_len = round_page4k((vm_offset_t)vmaddr + memsz) - map_addr;
-
- /* This had damn well better be true! */
- if (map_len != 0) {
- rv = elf32_map_insert(&vmspace->vm_map, NULL, 0,
- map_addr, map_addr + map_len,
- VM_PROT_ALL, VM_PROT_ALL, 0);
- if (rv != KERN_SUCCESS) {
- return EINVAL;
- }
- }
-
- if (copy_len != 0) {
- vm_offset_t off;
- vm_object_reference(object);
- rv = vm_map_find(exec_map,
- object,
- trunc_page(offset + filsz),
- &data_buf,
- PAGE_SIZE,
- TRUE,
- VM_PROT_READ,
- VM_PROT_ALL,
- MAP_COPY_ON_WRITE | MAP_PREFAULT_PARTIAL);
- if (rv != KERN_SUCCESS) {
- vm_object_deallocate(object);
- return EINVAL;
- }
-
- /* send the page fragment to user space */
- off = trunc_page4k(offset + filsz) - trunc_page(offset + filsz);
- error = copyout((caddr_t)data_buf+off, (caddr_t)map_addr, copy_len);
- vm_map_remove(exec_map, data_buf, data_buf + PAGE_SIZE);
- if (error) {
- return (error);
- }
- }
-
- /*
- * set it to the specified protection
- */
- vm_map_protect(&vmspace->vm_map, map_addr, map_addr + map_len, prot,
- FALSE);
-
- return error;
-}
-
-/*
- * Load the file "file" into memory. It may be either a shared object
- * or an executable.
- *
- * The "addr" reference parameter is in/out. On entry, it specifies
- * the address where a shared object should be loaded. If the file is
- * an executable, this value is ignored. On exit, "addr" specifies
- * where the file was actually loaded.
- *
- * The "entry" reference parameter is out only. On exit, it specifies
- * the entry point for the loaded file.
- */
-static int
-elf32_load_file(struct proc *p, const char *file, u_long *addr, u_long *entry)
-{
- struct {
- struct nameidata nd;
- struct vattr attr;
- struct image_params image_params;
- } *tempdata;
- const Elf32_Ehdr *hdr = NULL;
- const Elf32_Phdr *phdr = NULL;
- struct nameidata *nd;
- struct vmspace *vmspace = p->p_vmspace;
- struct vattr *attr;
- struct image_params *imgp;
- vm_prot_t prot;
- u_long rbase;
- u_long base_addr = 0;
- int error, i, numsegs;
-
- if (curthread->td_proc != p)
- panic("elf32_load_file - thread"); /* XXXKSE DIAGNOSTIC */
-
- tempdata = malloc(sizeof(*tempdata), M_TEMP, M_WAITOK);
- nd = &tempdata->nd;
- attr = &tempdata->attr;
- imgp = &tempdata->image_params;
-
- /*
- * Initialize part of the common data
- */
- imgp->proc = p;
- imgp->uap = NULL;
- imgp->attr = attr;
- imgp->firstpage = NULL;
- imgp->image_header = (char *)kmem_alloc_wait(exec_map, PAGE_SIZE);
-
- if (imgp->image_header == NULL) {
- nd->ni_vp = NULL;
- error = ENOMEM;
- goto fail;
- }
-
- /* XXXKSE */
- NDINIT(nd, LOOKUP, LOCKLEAF|FOLLOW, UIO_SYSSPACE, file, curthread);
-
- if ((error = namei(nd)) != 0) {
- nd->ni_vp = NULL;
- goto fail;
- }
- NDFREE(nd, NDF_ONLY_PNBUF);
- imgp->vp = nd->ni_vp;
-
- /*
- * Check permissions, modes, uid, etc on the file, and "open" it.
- */
- error = exec_check_permissions(imgp);
- if (error) {
- VOP_UNLOCK(nd->ni_vp, 0, curthread); /* XXXKSE */
- goto fail;
- }
-
- error = exec_map_first_page(imgp);
- /*
- * Also make certain that the interpreter stays the same, so set
- * its VTEXT flag, too.
- */
- if (error == 0)
- nd->ni_vp->v_flag |= VTEXT;
- VOP_UNLOCK(nd->ni_vp, 0, curthread); /* XXXKSE */
- if (error)
- goto fail;
-
- hdr = (const Elf32_Ehdr *)imgp->image_header;
- if ((error = elf32_check_header(hdr)) != 0)
- goto fail;
- if (hdr->e_type == ET_DYN)
- rbase = *addr;
- else if (hdr->e_type == ET_EXEC)
- rbase = 0;
- else {
- error = ENOEXEC;
- goto fail;
- }
-
- /* Only support headers that fit within first page for now */
- if ((hdr->e_phoff > PAGE_SIZE) ||
- (hdr->e_phoff + hdr->e_phentsize * hdr->e_phnum) > PAGE_SIZE) {
- error = ENOEXEC;
- goto fail;
- }
-
- phdr = (const Elf32_Phdr *)(imgp->image_header + hdr->e_phoff);
-
- for (i = 0, numsegs = 0; i < hdr->e_phnum; i++) {
- if (phdr[i].p_type == PT_LOAD) { /* Loadable segment */
- prot = 0;
- if (phdr[i].p_flags & PF_X)
- prot |= VM_PROT_EXECUTE;
- if (phdr[i].p_flags & PF_W)
- prot |= VM_PROT_WRITE;
- if (phdr[i].p_flags & PF_R)
- prot |= VM_PROT_READ;
-
- if ((error = elf32_load_section(p, vmspace, nd->ni_vp,
- phdr[i].p_offset,
- (caddr_t)(uintptr_t)phdr[i].p_vaddr +
- rbase,
- phdr[i].p_memsz,
- phdr[i].p_filesz, prot)) != 0)
- goto fail;
- /*
- * Establish the base address if this is the
- * first segment.
- */
- if (numsegs == 0)
- base_addr = trunc_page(phdr[i].p_vaddr + rbase);
- numsegs++;
- }
- }
- *addr = base_addr;
- *entry=(unsigned long)hdr->e_entry + rbase;
-
-fail:
- if (imgp->firstpage)
- exec_unmap_first_page(imgp);
- if (imgp->image_header)
- kmem_free_wakeup(exec_map, (vm_offset_t)imgp->image_header,
- PAGE_SIZE);
- if (nd->ni_vp)
- vrele(nd->ni_vp);
-
- free(tempdata, M_TEMP);
-
- return error;
-}
-
-/*
- * non static, as it can be overridden by start_init()
- */
-#ifdef __ia64__
-int fallback_elf32_brand = ELFOSABI_FREEBSD;
-#else
-int fallback_elf32_brand = -1;
-#endif
-SYSCTL_INT(_kern, OID_AUTO, fallback_elf32_brand, CTLFLAG_RW,
- &fallback_elf32_brand, -1,
- "ELF brand of last resort");
-
-static int
-exec_elf32_imgact(struct image_params *imgp)
-{
- const Elf32_Ehdr *hdr = (const Elf32_Ehdr *) imgp->image_header;
- const Elf32_Phdr *phdr;
- Elf32_Auxargs *elf32_auxargs = NULL;
- struct vmspace *vmspace;
- vm_prot_t prot;
- u_long text_size = 0, data_size = 0;
- u_long text_addr = 0, data_addr = 0;
- u_long addr, entry = 0, proghdr = 0;
- int error, i;
- const char *interp = NULL;
- Elf32_Brandinfo *brand_info;
- char *path;
-
- GIANT_REQUIRED;
-
- /*
- * Do we have a valid ELF header ?
- */
- if (elf32_check_header(hdr) != 0 || hdr->e_type != ET_EXEC)
- return -1;
-
- /*
- * From here on down, we return an errno, not -1, as we've
- * detected an ELF file.
- */
-
- if ((hdr->e_phoff > PAGE_SIZE) ||
- (hdr->e_phoff + hdr->e_phentsize * hdr->e_phnum) > PAGE_SIZE) {
- /* Only support headers in first page for now */
- return ENOEXEC;
- }
- phdr = (const Elf32_Phdr*)(imgp->image_header + hdr->e_phoff);
-
- /*
- * From this point on, we may have resources that need to be freed.
- */
-
- /*
- * Yeah, I'm paranoid. There is every reason in the world to get
- * VTEXT now since from here on out, there are places we can have
- * a context switch. Better safe than sorry; I really don't want
- * the file to change while it's being loaded.
- */
- mtx_lock(&imgp->vp->v_interlock);
- imgp->vp->v_flag |= VTEXT;
- mtx_unlock(&imgp->vp->v_interlock);
-
- if ((error = exec_extract_strings(imgp)) != 0)
- goto fail;
-
- exec_new_vmspace(imgp, IA32_USRSTACK);
-
- vmspace = imgp->proc->p_vmspace;
-
- for (i = 0; i < hdr->e_phnum; i++) {
- switch(phdr[i].p_type) {
-
- case PT_LOAD: /* Loadable segment */
- prot = 0;
- if (phdr[i].p_flags & PF_X)
- prot |= VM_PROT_EXECUTE;
- if (phdr[i].p_flags & PF_W)
- prot |= VM_PROT_WRITE;
- if (phdr[i].p_flags & PF_R)
- prot |= VM_PROT_READ;
-
- if ((error = elf32_load_section(imgp->proc,
- vmspace, imgp->vp,
- phdr[i].p_offset,
- (caddr_t)(uintptr_t)phdr[i].p_vaddr,
- phdr[i].p_memsz,
- phdr[i].p_filesz, prot)) != 0)
- goto fail;
-
- /*
- * Is this .text or .data ??
- *
- * We only handle one each of those yet XXX
- */
- if (hdr->e_entry >= phdr[i].p_vaddr &&
- hdr->e_entry <(phdr[i].p_vaddr+phdr[i].p_memsz)) {
- text_addr = trunc_page(phdr[i].p_vaddr);
- text_size = round_page(phdr[i].p_memsz +
- phdr[i].p_vaddr -
- text_addr);
- entry = (u_long)hdr->e_entry;
- } else {
- data_addr = trunc_page(phdr[i].p_vaddr);
- data_size = round_page(phdr[i].p_memsz +
- phdr[i].p_vaddr -
- data_addr);
- }
- break;
- case PT_INTERP: /* Path to interpreter */
- if (phdr[i].p_filesz > MAXPATHLEN ||
- phdr[i].p_offset + phdr[i].p_filesz > PAGE_SIZE) {
- error = ENOEXEC;
- goto fail;
- }
- interp = imgp->image_header + phdr[i].p_offset;
- break;
- case PT_PHDR: /* Program header table info */
- proghdr = phdr[i].p_vaddr;
- break;
- default:
- break;
- }
- }
-
- vmspace->vm_tsize = text_size >> PAGE_SHIFT;
- vmspace->vm_taddr = (caddr_t)(uintptr_t)text_addr;
- vmspace->vm_dsize = data_size >> PAGE_SHIFT;
- vmspace->vm_daddr = (caddr_t)(uintptr_t)data_addr;
-
- addr = ELF_RTLD_ADDR(vmspace);
-
- imgp->entry_addr = entry;
-
- brand_info = NULL;
-
- /* We support three types of branding -- (1) the ELF EI_OSABI field
- * that SCO added to the ELF spec, (2) FreeBSD 3.x's traditional string
- * branding w/in the ELF header, and (3) path of the `interp_path'
- * field. We should also look for an ".note.ABI-tag" ELF section now
- * in all Linux ELF binaries, FreeBSD 4.1+, and some NetBSD ones.
- */
-
- /* If the executable has a brand, search for it in the brand list. */
- if (brand_info == NULL) {
- for (i = 0; i < MAX_BRANDS; i++) {
- Elf32_Brandinfo *bi = elf32_brand_list[i];
-
- if (bi != NULL &&
- (hdr->e_ident[EI_OSABI] == bi->brand
- || 0 ==
- strncmp((const char *)&hdr->e_ident[OLD_EI_BRAND],
- bi->compat_3_brand, strlen(bi->compat_3_brand)))) {
- brand_info = bi;
- break;
- }
- }
- }
-
- /* Lacking a known brand, search for a recognized interpreter. */
- if (brand_info == NULL && interp != NULL) {
- for (i = 0; i < MAX_BRANDS; i++) {
- Elf32_Brandinfo *bi = elf32_brand_list[i];
-
- if (bi != NULL &&
- strcmp(interp, bi->interp_path) == 0) {
- brand_info = bi;
- break;
- }
- }
- }
-
- /* Lacking a recognized interpreter, try the default brand */
- if (brand_info == NULL) {
- for (i = 0; i < MAX_BRANDS; i++) {
- Elf32_Brandinfo *bi = elf32_brand_list[i];
-
- if (bi != NULL && fallback_elf32_brand == bi->brand) {
- brand_info = bi;
- break;
- }
- }
- }
-
- if (brand_info == NULL) {
- uprintf("ELF binary type \"%u\" not known.\n",
- hdr->e_ident[EI_OSABI]);
- error = ENOEXEC;
- goto fail;
- }
-
- imgp->proc->p_sysent = brand_info->sysvec;
- if (interp != NULL) {
- path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
- snprintf(path, MAXPATHLEN, "%s%s",
- brand_info->emul_path, interp);
- if ((error = elf32_load_file(imgp->proc, path, &addr,
- &imgp->entry_addr)) != 0) {
- if ((error = elf32_load_file(imgp->proc, interp, &addr,
- &imgp->entry_addr)) != 0) {
- uprintf("ELF interpreter %s not found\n", path);
- free(path, M_TEMP);
- goto fail;
- }
- }
- free(path, M_TEMP);
- }
-
- /*
- * Construct auxargs table (used by the fixup routine)
- */
- elf32_auxargs = malloc(sizeof(Elf32_Auxargs), M_TEMP, M_WAITOK);
- elf32_auxargs->execfd = -1;
- elf32_auxargs->phdr = proghdr;
- elf32_auxargs->phent = hdr->e_phentsize;
- elf32_auxargs->phnum = hdr->e_phnum;
- elf32_auxargs->pagesz = PAGE_SIZE;
- elf32_auxargs->base = addr;
- elf32_auxargs->flags = 0;
- elf32_auxargs->entry = entry;
- elf32_auxargs->trace = elf32_trace;
-
- imgp->auxargs = elf32_auxargs;
- imgp->interpreted = 0;
-
-fail:
- return error;
-}
-
-#define AUXARGS32_ENTRY(pos, id, val) { \
- suword32(pos++, id); \
- suword32(pos++, val); \
-}
-
-static int
-elf32_freebsd_fixup(register_t **stack_base, struct image_params *imgp)
-{
- Elf32_Auxargs *args = (Elf32_Auxargs *)imgp->auxargs;
- u_int32_t *pos;
-
- pos = *(u_int32_t **)stack_base + (imgp->argc + imgp->envc + 2);
-
- if (args->trace) {
- AUXARGS32_ENTRY(pos, AT_DEBUG, 1);
- }
- if (args->execfd != -1) {
- AUXARGS32_ENTRY(pos, AT_EXECFD, args->execfd);
- }
- AUXARGS32_ENTRY(pos, AT_PHDR, args->phdr);
- AUXARGS32_ENTRY(pos, AT_PHENT, args->phent);
- AUXARGS32_ENTRY(pos, AT_PHNUM, args->phnum);
- AUXARGS32_ENTRY(pos, AT_PAGESZ, args->pagesz);
- AUXARGS32_ENTRY(pos, AT_FLAGS, args->flags);
- AUXARGS32_ENTRY(pos, AT_ENTRY, args->entry);
- AUXARGS32_ENTRY(pos, AT_BASE, args->base);
- AUXARGS32_ENTRY(pos, AT_NULL, 0);
-
- free(imgp->auxargs, M_TEMP);
- imgp->auxargs = NULL;
-
- (*(u_int32_t **)stack_base)--;
- suword32(*stack_base, (long) imgp->argc);
- return 0;
-}
-
-/*
- * Code for generating ELF core dumps.
- */
-
-typedef void (*segment_callback)(vm_map_entry_t, void *);
-
-/* Closure for cb_put_phdr(). */
-struct phdr_closure {
- Elf32_Phdr *phdr; /* Program header to fill in */
- Elf32_Off offset; /* Offset of segment in core file */
-};
-
-/* Closure for cb_size_segment(). */
-struct sseg_closure {
- int count; /* Count of writable segments. */
- size_t size; /* Total size of all writable segments. */
-};
-
-static void cb_put_phdr(vm_map_entry_t, void *);
-static void cb_size_segment(vm_map_entry_t, void *);
-static void each_writable_segment(struct proc *, segment_callback, void *);
-static int elf32_corehdr(struct thread *, struct vnode *, struct ucred *,
- int, void *, size_t);
-static void elf32_puthdr(struct proc *, void *, size_t *,
- const prstatus_t *, const prfpregset_t *, const prpsinfo_t *, int);
-static void elf32_putnote(void *, size_t *, const char *, int,
- const void *, size_t);
-
-extern int osreldate;
-
-static int
-elf32_coredump(td, vp, limit)
- struct thread *td;
- register struct vnode *vp;
- off_t limit;
-{
- register struct proc *p = td->td_proc;
- register struct ucred *cred = td->td_ucred;
- int error = 0;
- struct sseg_closure seginfo;
- void *hdr;
- size_t hdrsize;
-
- /* Size the program segments. */
- seginfo.count = 0;
- seginfo.size = 0;
- each_writable_segment(p, cb_size_segment, &seginfo);
-
- /*
- * Calculate the size of the core file header area by making
- * a dry run of generating it. Nothing is written, but the
- * size is calculated.
- */
- hdrsize = 0;
- elf32_puthdr((struct proc *)NULL, (void *)NULL, &hdrsize,
- (const prstatus_t *)NULL, (const prfpregset_t *)NULL,
- (const prpsinfo_t *)NULL, seginfo.count);
-
- if (hdrsize + seginfo.size >= limit)
- return (EFAULT);
-
- /*
- * Allocate memory for building the header, fill it up,
- * and write it out.
- */
- hdr = malloc(hdrsize, M_TEMP, M_WAITOK);
- if (hdr == NULL) {
- return EINVAL;
- }
- error = elf32_corehdr(td, vp, cred, seginfo.count, hdr, hdrsize);
-
- /* Write the contents of all of the writable segments. */
- if (error == 0) {
- Elf32_Phdr *php;
- off_t offset;
- int i;
-
- php = (Elf32_Phdr *)((char *)hdr + sizeof(Elf32_Ehdr)) + 1;
- offset = hdrsize;
- for (i = 0; i < seginfo.count; i++) {
- error = vn_rdwr_inchunks(UIO_WRITE, vp,
- (caddr_t)(uintptr_t)php->p_vaddr,
- php->p_filesz, offset, UIO_USERSPACE,
- IO_UNIT | IO_DIRECT, cred, (int *)NULL, curthread); /* XXXKSE */
- if (error != 0)
- break;
- offset += php->p_filesz;
- php++;
- }
- }
- free(hdr, M_TEMP);
-
- return error;
-}
-
-/*
- * A callback for each_writable_segment() to write out the segment's
- * program header entry.
- */
-static void
-cb_put_phdr(entry, closure)
- vm_map_entry_t entry;
- void *closure;
-{
- struct phdr_closure *phc = (struct phdr_closure *)closure;
- Elf32_Phdr *phdr = phc->phdr;
-
- phc->offset = round_page(phc->offset);
-
- phdr->p_type = PT_LOAD;
- phdr->p_offset = phc->offset;
- phdr->p_vaddr = entry->start;
- phdr->p_paddr = 0;
- phdr->p_filesz = phdr->p_memsz = entry->end - entry->start;
- phdr->p_align = PAGE_SIZE;
- phdr->p_flags = 0;
- if (entry->protection & VM_PROT_READ)
- phdr->p_flags |= PF_R;
- if (entry->protection & VM_PROT_WRITE)
- phdr->p_flags |= PF_W;
- if (entry->protection & VM_PROT_EXECUTE)
- phdr->p_flags |= PF_X;
-
- phc->offset += phdr->p_filesz;
- phc->phdr++;
-}
-
-/*
- * A callback for each_writable_segment() to gather information about
- * the number of segments and their total size.
- */
-static void
-cb_size_segment(entry, closure)
- vm_map_entry_t entry;
- void *closure;
-{
- struct sseg_closure *ssc = (struct sseg_closure *)closure;
-
- ssc->count++;
- ssc->size += entry->end - entry->start;
-}
-
-/*
- * For each writable segment in the process's memory map, call the given
- * function with a pointer to the map entry and some arbitrary
- * caller-supplied data.
- */
-static void
-each_writable_segment(p, func, closure)
- struct proc *p;
- segment_callback func;
- void *closure;
-{
- vm_map_t map = &p->p_vmspace->vm_map;
- vm_map_entry_t entry;
-
- for (entry = map->header.next; entry != &map->header;
- entry = entry->next) {
- vm_object_t obj;
-
- if ((entry->eflags & MAP_ENTRY_IS_SUB_MAP) ||
- (entry->protection & (VM_PROT_READ|VM_PROT_WRITE)) !=
- (VM_PROT_READ|VM_PROT_WRITE))
- continue;
-
- /*
- ** Dont include memory segment in the coredump if
- ** MAP_NOCORE is set in mmap(2) or MADV_NOCORE in
- ** madvise(2).
- */
- if (entry->eflags & MAP_ENTRY_NOCOREDUMP)
- continue;
-
- if ((obj = entry->object.vm_object) == NULL)
- continue;
-
- /* Find the deepest backing object. */
- while (obj->backing_object != NULL)
- obj = obj->backing_object;
-
- /* Ignore memory-mapped devices and such things. */
- if (obj->type != OBJT_DEFAULT &&
- obj->type != OBJT_SWAP &&
- obj->type != OBJT_VNODE)
- continue;
-
- (*func)(entry, closure);
- }
-}
-
-/*
- * Write the core file header to the file, including padding up to
- * the page boundary.
- */
-static int
-elf32_corehdr(td, vp, cred, numsegs, hdr, hdrsize)
- struct thread *td;
- struct vnode *vp;
- struct ucred *cred;
- int numsegs;
- size_t hdrsize;
- void *hdr;
-{
- struct {
- prstatus_t status;
- prfpregset_t fpregset;
- prpsinfo_t psinfo;
- } *tempdata;
- struct proc *p = td->td_proc;
- size_t off;
- prstatus_t *status;
- prfpregset_t *fpregset;
- prpsinfo_t *psinfo;
-
- tempdata = malloc(sizeof(*tempdata), M_TEMP, M_ZERO | M_WAITOK);
- status = &tempdata->status;
- fpregset = &tempdata->fpregset;
- psinfo = &tempdata->psinfo;
-
- /* Gather the information for the header. */
- status->pr_version = PRSTATUS_VERSION;
- status->pr_statussz = sizeof(prstatus_t);
- status->pr_gregsetsz = sizeof(gregset_t);
- status->pr_fpregsetsz = sizeof(fpregset_t);
- status->pr_osreldate = osreldate;
- status->pr_cursig = p->p_sig;
- status->pr_pid = p->p_pid;
- fill_regs(td, &status->pr_reg);
-
- fill_fpregs(td, fpregset);
-
- psinfo->pr_version = PRPSINFO_VERSION;
- psinfo->pr_psinfosz = sizeof(prpsinfo_t);
- strncpy(psinfo->pr_fname, p->p_comm, sizeof(psinfo->pr_fname) - 1);
-
- /* XXX - We don't fill in the command line arguments properly yet. */
- strncpy(psinfo->pr_psargs, p->p_comm, PRARGSZ);
-
- /* Fill in the header. */
- bzero(hdr, hdrsize);
- off = 0;
- elf32_puthdr(p, hdr, &off, status, fpregset, psinfo, numsegs);
-
- free(tempdata, M_TEMP);
-
- /* Write it to the core file. */
- return vn_rdwr_inchunks(UIO_WRITE, vp, hdr, hdrsize, (off_t)0,
- UIO_SYSSPACE, IO_UNIT | IO_DIRECT, cred, NULL, td); /* XXXKSE */
-}
-
-static void
-elf32_puthdr(struct proc *p, void *dst, size_t *off, const prstatus_t *status,
- const prfpregset_t *fpregset, const prpsinfo_t *psinfo, int numsegs)
-{
- size_t ehoff;
- size_t phoff;
- size_t noteoff;
- size_t notesz;
-
- ehoff = *off;
- *off += sizeof(Elf32_Ehdr);
-
- phoff = *off;
- *off += (numsegs + 1) * sizeof(Elf32_Phdr);
-
- noteoff = *off;
- elf32_putnote(dst, off, "FreeBSD", NT_PRSTATUS, status,
- sizeof *status);
- elf32_putnote(dst, off, "FreeBSD", NT_FPREGSET, fpregset,
- sizeof *fpregset);
- elf32_putnote(dst, off, "FreeBSD", NT_PRPSINFO, psinfo,
- sizeof *psinfo);
- notesz = *off - noteoff;
-
- /* Align up to a page boundary for the program segments. */
- *off = round_page(*off);
-
- if (dst != NULL) {
- Elf32_Ehdr *ehdr;
- Elf32_Phdr *phdr;
- struct phdr_closure phc;
-
- /*
- * Fill in the ELF header.
- */
- ehdr = (Elf32_Ehdr *)((char *)dst + ehoff);
- ehdr->e_ident[EI_MAG0] = ELFMAG0;
- ehdr->e_ident[EI_MAG1] = ELFMAG1;
- ehdr->e_ident[EI_MAG2] = ELFMAG2;
- ehdr->e_ident[EI_MAG3] = ELFMAG3;
- ehdr->e_ident[EI_CLASS] = ELF_CLASS;
- ehdr->e_ident[EI_DATA] = ELF_DATA;
- ehdr->e_ident[EI_VERSION] = EV_CURRENT;
- ehdr->e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
- ehdr->e_ident[EI_ABIVERSION] = 0;
- ehdr->e_ident[EI_PAD] = 0;
- ehdr->e_type = ET_CORE;
- ehdr->e_machine = ELF_ARCH;
- ehdr->e_version = EV_CURRENT;
- ehdr->e_entry = 0;
- ehdr->e_phoff = phoff;
- ehdr->e_flags = 0;
- ehdr->e_ehsize = sizeof(Elf32_Ehdr);
- ehdr->e_phentsize = sizeof(Elf32_Phdr);
- ehdr->e_phnum = numsegs + 1;
- ehdr->e_shentsize = sizeof(Elf32_Shdr);
- ehdr->e_shnum = 0;
- ehdr->e_shstrndx = SHN_UNDEF;
-
- /*
- * Fill in the program header entries.
- */
- phdr = (Elf32_Phdr *)((char *)dst + phoff);
-
- /* The note segement. */
- phdr->p_type = PT_NOTE;
- phdr->p_offset = noteoff;
- phdr->p_vaddr = 0;
- phdr->p_paddr = 0;
- phdr->p_filesz = notesz;
- phdr->p_memsz = 0;
- phdr->p_flags = 0;
- phdr->p_align = 0;
- phdr++;
-
- /* All the writable segments from the program. */
- phc.phdr = phdr;
- phc.offset = *off;
- each_writable_segment(p, cb_put_phdr, &phc);
- }
-}
-
-static void
-elf32_putnote(void *dst, size_t *off, const char *name, int type,
- const void *desc, size_t descsz)
-{
- Elf_Note note;
-
- note.n_namesz = strlen(name) + 1;
- note.n_descsz = descsz;
- note.n_type = type;
- if (dst != NULL)
- bcopy(&note, (char *)dst + *off, sizeof note);
- *off += sizeof note;
- if (dst != NULL)
- bcopy(name, (char *)dst + *off, note.n_namesz);
- *off += roundup2(note.n_namesz, sizeof(Elf32_Size));
- if (dst != NULL)
- bcopy(desc, (char *)dst + *off, note.n_descsz);
- *off += roundup2(note.n_descsz, sizeof(Elf32_Size));
-}
-
-struct ia32_ps_strings {
- u_int32_t ps_argvstr; /* first of 0 or more argument strings */
- int ps_nargvstr; /* the number of argument strings */
- u_int32_t ps_envstr; /* first of 0 or more environment strings */
- int ps_nenvstr; /* the number of environment strings */
-};
-
-static register_t *
-elf32_copyout_strings(struct image_params *imgp)
-{
- int argc, envc;
- u_int32_t *vectp;
- char *stringp, *destp;
- u_int32_t *stack_base;
- struct ia32_ps_strings *arginfo;
- int szsigcode;
-
- /*
- * Calculate string base and vector table pointers.
- * Also deal with signal trampoline code for this exec type.
- */
- arginfo = (struct ia32_ps_strings *)IA32_PS_STRINGS;
- szsigcode = *(imgp->proc->p_sysent->sv_szsigcode);
- destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE -
- roundup((ARG_MAX - imgp->stringspace), sizeof(char *));
-
- /*
- * install sigcode
- */
- if (szsigcode)
- copyout(imgp->proc->p_sysent->sv_sigcode,
- ((caddr_t)arginfo - szsigcode), szsigcode);
-
- /*
- * If we have a valid auxargs ptr, prepare some room
- * on the stack.
- */
- if (imgp->auxargs) {
- /*
- * 'AT_COUNT*2' is size for the ELF Auxargs data. This is for
- * lower compatibility.
- */
- imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size
- : (AT_COUNT * 2);
- /*
- * The '+ 2' is for the null pointers at the end of each of
- * the arg and env vector sets,and imgp->auxarg_size is room
- * for argument of Runtime loader.
- */
- vectp = (u_int32_t *) (destp - (imgp->argc + imgp->envc + 2 +
- imgp->auxarg_size) * sizeof(u_int32_t));
-
- } else
- /*
- * The '+ 2' is for the null pointers at the end of each of
- * the arg and env vector sets
- */
- vectp = (u_int32_t *)
- (destp - (imgp->argc + imgp->envc + 2) * sizeof(u_int32_t));
-
- /*
- * vectp also becomes our initial stack base
- */
- stack_base = vectp;
-
- stringp = imgp->stringbase;
- argc = imgp->argc;
- envc = imgp->envc;
-
- /*
- * Copy out strings - arguments and environment.
- */
- copyout(stringp, destp, ARG_MAX - imgp->stringspace);
-
- /*
- * Fill in "ps_strings" struct for ps, w, etc.
- */
- suword32(&arginfo->ps_argvstr, (u_int32_t)(intptr_t)vectp);
- suword32(&arginfo->ps_nargvstr, argc);
-
- /*
- * Fill in argument portion of vector table.
- */
- for (; argc > 0; --argc) {
- suword32(vectp++, (u_int32_t)(intptr_t)destp);
- while (*stringp++ != 0)
- destp++;
- destp++;
- }
-
- /* a null vector table pointer separates the argp's from the envp's */
- suword32(vectp++, 0);
-
- suword32(&arginfo->ps_envstr, (u_int32_t)(intptr_t)vectp);
- suword32(&arginfo->ps_nenvstr, envc);
-
- /*
- * Fill in environment portion of vector table.
- */
- for (; envc > 0; --envc) {
- suword32(vectp++, (u_int32_t)(intptr_t)destp);
- while (*stringp++ != 0)
- destp++;
- destp++;
- }
-
- /* end of vector table is a null pointer */
- suword32(vectp, 0);
-
- return ((register_t *)stack_base);
-}
-
-static void
-elf32_setregs(struct thread *td, u_long entry, u_long stack,
- u_long ps_strings)
-{
- struct trapframe *frame = td->td_frame;
- vm_offset_t gdt, ldt;
- u_int64_t codesel, datasel, ldtsel;
- u_int64_t codeseg, dataseg, gdtseg, ldtseg;
- struct segment_descriptor desc;
- struct vmspace *vmspace = td->td_proc->p_vmspace;
-
- /*
- * Make sure that we restore the entire trapframe after an
- * execve.
- */
- frame->tf_flags &= ~FRAME_SYSCALL;
-
- bzero(frame->tf_r, sizeof(frame->tf_r));
- bzero(frame->tf_f, sizeof(frame->tf_f));
-
- frame->tf_cr_iip = entry;
- frame->tf_cr_ipsr = (IA64_PSR_IC
- | IA64_PSR_I
- | IA64_PSR_IT
- | IA64_PSR_DT
- | IA64_PSR_RT
- | IA64_PSR_IS
- | IA64_PSR_BN
- | IA64_PSR_CPL_USER);
- frame->tf_r[FRAME_R12] = stack;
-
- codesel = LSEL(LUCODE_SEL, SEL_UPL);
- datasel = LSEL(LUDATA_SEL, SEL_UPL);
- ldtsel = GSEL(GLDT_SEL, SEL_UPL);
-
-#if 1
- frame->tf_r[FRAME_R16] = (datasel << 48) | (datasel << 32)
- | (datasel << 16) | datasel;
- frame->tf_r[FRAME_R17] = (ldtsel << 32) | (datasel << 16) | codesel;
-#else
- frame->tf_r[FRAME_R16] = datasel;
- frame->tf_r[FRAME_R17] = codesel;
- frame->tf_r[FRAME_R18] = datasel;
- frame->tf_r[FRAME_R19] = datasel;
- frame->tf_r[FRAME_R20] = datasel;
- frame->tf_r[FRAME_R21] = datasel;
- frame->tf_r[FRAME_R22] = ldtsel;
-#endif
-
- /*
- * Build the GDT and LDT.
- */
- gdt = IA32_USRSTACK;
- vm_map_find(&vmspace->vm_map, 0, 0,
- &gdt, PAGE_SIZE, 0,
- VM_PROT_ALL, VM_PROT_ALL, 0);
- ldt = gdt + 4096;
-
- desc.sd_lolimit = 8*NLDT-1;
- desc.sd_lobase = ldt & 0xffffff;
- desc.sd_type = SDT_SYSLDT;
- desc.sd_dpl = SEL_UPL;
- desc.sd_p = 1;
- desc.sd_hilimit = 0;
- desc.sd_def32 = 0;
- desc.sd_gran = 0;
- desc.sd_hibase = ldt >> 24;
- copyout(&desc, (caddr_t) gdt + 8*GLDT_SEL, sizeof(desc));
-
- desc.sd_lolimit = ((IA32_USRSTACK >> 12) - 1) & 0xffff;
- desc.sd_lobase = 0;
- desc.sd_type = SDT_MEMERA;
- desc.sd_dpl = SEL_UPL;
- desc.sd_p = 1;
- desc.sd_hilimit = ((IA32_USRSTACK >> 12) - 1) >> 16;
- desc.sd_def32 = 1;
- desc.sd_gran = 1;
- desc.sd_hibase = 0;
- copyout(&desc, (caddr_t) ldt + 8*LUCODE_SEL, sizeof(desc));
- desc.sd_type = SDT_MEMRWA;
- copyout(&desc, (caddr_t) ldt + 8*LUDATA_SEL, sizeof(desc));
-
- codeseg = 0 /* base */
- + (((IA32_USRSTACK >> 12) - 1) << 32) /* limit */
- + ((long)SDT_MEMERA << 52)
- + ((long)SEL_UPL << 57)
- + (1L << 59) /* present */
- + (1L << 62) /* 32 bits */
- + (1L << 63); /* page granularity */
- dataseg = 0 /* base */
- + (((IA32_USRSTACK >> 12) - 1) << 32) /* limit */
- + ((long)SDT_MEMRWA << 52)
- + ((long)SEL_UPL << 57)
- + (1L << 59) /* present */
- + (1L << 62) /* 32 bits */
- + (1L << 63); /* page granularity */
- ia64_set_csd(codeseg);
- ia64_set_ssd(dataseg);
- frame->tf_r[FRAME_R24] = dataseg; /* ESD */
- frame->tf_r[FRAME_R27] = dataseg; /* DSD */
- frame->tf_r[FRAME_R28] = dataseg; /* FSD */
- frame->tf_r[FRAME_R29] = dataseg; /* GSD */
-
- gdtseg = gdt /* base */
- + ((8L*NGDT - 1) << 32) /* limit */
- + ((long)SDT_SYSNULL << 52)
- + ((long)SEL_UPL << 57)
- + (1L << 59) /* present */
- + (0L << 62) /* 16 bits */
- + (0L << 63); /* byte granularity */
- ldtseg = ldt /* base */
- + ((8L*NLDT - 1) << 32) /* limit */
- + ((long)SDT_SYSLDT << 52)
- + ((long)SEL_UPL << 57)
- + (1L << 59) /* present */
- + (0L << 62) /* 16 bits */
- + (0L << 63); /* byte granularity */
- frame->tf_r[FRAME_R30] = ldtseg; /* LDTD */
- frame->tf_r[FRAME_R31] = gdtseg; /* GDTD */
-
- ia64_set_eflag(PSL_USER);
-
- /* PS_STRINGS value for BSD/OS binaries. It is 0 for non-BSD/OS. */
- frame->tf_r[FRAME_R11] = ps_strings;
-
- /*
- * Set ia32 control registers.
- */
- ia64_set_cflg((CR0_PE | CR0_PG)
- | ((long)(CR4_XMM | CR4_FXSR) << 32));
-
- /*
- * XXX - Linux emulator
- * Make sure sure edx is 0x0 on entry. Linux binaries depend
- * on it.
- */
- td->td_retval[1] = 0;
-}
-
-/*
- * Tell kern_execve.c about it, with a little help from the linker.
- */
-static struct execsw elf32_execsw = {exec_elf32_imgact, "ELF32"};
-EXEC_SET(elf32, elf32_execsw);
diff --git a/sys/ia64/ia32/imgact_ia32.h b/sys/ia64/ia32/imgact_ia32.h
deleted file mode 100644
index 9551bf7c780f..000000000000
--- a/sys/ia64/ia32/imgact_ia32.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*-
- * Copyright (c) 1995-1996 Søren Schmidt
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer
- * in this position and unchanged.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _IA64_IA32_IMGACT_ELF_H_
-#define _IA64_IA32_IMGACT_ELF_H_
-
-#include <i386/include/elf.h>
-
-#ifdef _KERNEL
-
-#define AUXARGS_ENTRY(pos, id, val) {suword(pos++, id); suword(pos++, val);}
-
-#if ELF_TARG_CLASS == ELFCLASS32
-
-/*
- * Structure used to pass infomation from the loader to the
- * stack fixup routine.
- */
-typedef struct {
- Elf32_Sword execfd;
- Elf32_Word phdr;
- Elf32_Word phent;
- Elf32_Word phnum;
- Elf32_Word pagesz;
- Elf32_Word base;
- Elf32_Word flags;
- Elf32_Word entry;
- Elf32_Word trace;
-} Elf32_Auxargs;
-
-typedef struct {
- int brand;
- const char *compat_3_brand; /* pre Binutils 2.10 method (FBSD 3) */
- const char *emul_path;
- const char *interp_path;
- struct sysentvec *sysvec;
-} Elf32_Brandinfo;
-
-#define MAX_BRANDS 8
-
-int elf_brand_inuse(Elf32_Brandinfo *entry);
-int elf_insert_brand_entry(Elf32_Brandinfo *entry);
-int elf_remove_brand_entry(Elf32_Brandinfo *entry);
-
-#else /* !(ELF_TARG_CLASS == ELFCLASS32) */
-
-/*
- * Structure used to pass infomation from the loader to the
- * stack fixup routine.
- */
-typedef struct {
- Elf64_Sword execfd;
- Elf64_Addr phdr;
- Elf64_Word phent;
- Elf64_Word phnum;
- Elf64_Word pagesz;
- Elf64_Addr base;
- Elf64_Word flags;
- Elf64_Addr entry;
- Elf64_Word trace;
-} Elf64_Auxargs;
-
-typedef struct {
- int brand;
- const char *compat_3_brand; /* pre Binutils 2.10 method (FBSD 3) */
- const char *emul_path;
- const char *interp_path;
- struct sysentvec *sysvec;
-} Elf64_Brandinfo;
-
-#define MAX_BRANDS 8
-
-int elf_brand_inuse(Elf64_Brandinfo *entry);
-int elf_insert_brand_entry(Elf64_Brandinfo *entry);
-int elf_remove_brand_entry(Elf64_Brandinfo *entry);
-
-#endif /* ELF_TARG_CLASS == ELFCLASS32 */
-
-struct thread;
-
-int elf_coredump(struct thread *, struct vnode *, off_t);
-
-#endif /* _KERNEL */
-
-#endif /* !_IA64_IA32_IMGACT_ELF_H_ */
diff --git a/sys/ia64/ia32/syscalls.master b/sys/ia64/ia32/syscalls.master
index 347196a3da99..6de1c57b3665 100644
--- a/sys/ia64/ia32/syscalls.master
+++ b/sys/ia64/ia32/syscalls.master
@@ -36,6 +36,9 @@
#include <sys/param.h>
#include <sys/sysent.h>
#include <sys/sysproto.h>
+#include <sys/mount.h>
+#include <ia64/ia32/ia32.h>
+#include <ia64/ia32/ia32_proto.h>
; Reserved/unimplemented system calls in the range 0-150 inclusive
; are reserved for use in future Berkeley releases.
@@ -43,200 +46,189 @@
; redistributions should be placed in the reserved range at the end
; of the current calls.
-0 STD NOHIDE { int nosys(void); } syscall nosys_args int
-1 MSTD NOHIDE { void sys_exit(int rval); } exit sys_exit_args void
-2 MSTD POSIX { int fork(void); }
-3 MSTD POSIX { ssize_t read(int fd, void *buf, size_t nbyte); }
-4 MSTD POSIX { ssize_t write(int fd, const void *buf, size_t nbyte); }
-5 STD POSIX { int open(char *path, int flags, int mode); }
+0 MNOPROTO NOHIDE { int nosys(void); } syscall nosys_args int
+1 MNOPROTO NOHIDE { void sys_exit(int rval); } exit sys_exit_args void
+2 MNOPROTO POSIX { int fork(void); }
+3 MNOPROTO POSIX { ssize_t read(int fd, void *buf, size_t nbyte); }
+4 MNOPROTO POSIX { ssize_t write(int fd, const void *buf, size_t nbyte); }
+5 STD POSIX { int ia32_open(char *path, int flags, int mode); }
; XXX should be { int open(const char *path, int flags, ...); }
; but we're not ready for `const' or varargs.
; XXX man page says `mode_t mode'.
-6 MSTD POSIX { int close(int fd); }
-7 MSTD BSD { int wait4(int pid, int *status, int options, \
- struct rusage *rusage); } wait4 wait_args int
-8 COMPAT BSD { int creat(char *path, int mode); }
-9 STD POSIX { int link(char *path, char *link); }
-10 STD POSIX { int unlink(char *path); }
+6 MNOPROTO POSIX { int close(int fd); }
+7 MSTD BSD { int ia32_wait4(int pid, int *status, int options, \
+ struct rusage32 *rusage); }
+8 OBSOL BSD old creat
+9 NOPROTO POSIX { int link(char *path, char *link); }
+10 NOPROTO POSIX { int unlink(char *path); }
11 OBSOL NOHIDE execv
-12 STD POSIX { int chdir(char *path); }
-13 STD BSD { int fchdir(int fd); }
-14 STD POSIX { int mknod(char *path, int mode, int dev); }
-15 STD POSIX { int chmod(char *path, int mode); }
-16 STD POSIX { int chown(char *path, int uid, int gid); }
-17 MSTD BSD { int obreak(char *nsize); } break obreak_args int
-18 STD BSD { int getfsstat(struct statfs *buf, long bufsize, \
- int flags); }
-19 COMPAT POSIX { long lseek(int fd, long offset, int whence); }
-20 MSTD POSIX { pid_t getpid(void); }
-21 STD BSD { int mount(char *type, char *path, int flags, \
+12 NOPROTO POSIX { int chdir(char *path); }
+13 NOPROTO BSD { int fchdir(int fd); }
+14 NOPROTO POSIX { int mknod(char *path, int mode, int dev); }
+15 NOPROTO POSIX { int chmod(char *path, int mode); }
+16 NOPROTO POSIX { int chown(char *path, int uid, int gid); }
+17 MNOPROTO BSD { int obreak(char *nsize); } break obreak_args int
+18 STD BSD { int ia32_getfsstat(struct statfs32 *buf, \
+ long bufsize, int flags); }
+19 OBSOL POSIX olseek
+20 MNOPROTO POSIX { pid_t getpid(void); }
+21 NOPROTO BSD { int mount(char *type, char *path, int flags, \
caddr_t data); }
; XXX `path' should have type `const char *' but we're not ready for that.
-22 STD BSD { int unmount(char *path, int flags); }
-23 MSTD POSIX { int setuid(uid_t uid); }
-24 MSTD POSIX { uid_t getuid(void); }
-25 MSTD POSIX { uid_t geteuid(void); }
-26 STD BSD { int ptrace(int req, pid_t pid, caddr_t addr, \
+22 NOPROTO BSD { int unmount(char *path, int flags); }
+23 MNOPROTO POSIX { int setuid(uid_t uid); }
+24 MNOPROTO POSIX { uid_t getuid(void); }
+25 MNOPROTO POSIX { uid_t geteuid(void); }
+26 NOPROTO BSD { int ptrace(int req, pid_t pid, caddr_t addr, \
int data); }
-27 MSTD BSD { int recvmsg(int s, struct msghdr *msg, int flags); }
-28 MSTD BSD { int sendmsg(int s, caddr_t msg, int flags); }
-29 MSTD BSD { int recvfrom(int s, caddr_t buf, size_t len, \
+27 UNIMPL BSD recvmsg
+28 MNOPROTO BSD { int sendmsg(int s, caddr_t msg, int flags); }
+29 MNOPROTO BSD { int recvfrom(int s, caddr_t buf, size_t len, \
int flags, caddr_t from, int *fromlenaddr); }
-30 MSTD BSD { int accept(int s, caddr_t name, int *anamelen); }
-31 MSTD BSD { int getpeername(int fdes, caddr_t asa, int *alen); }
-32 MSTD BSD { int getsockname(int fdes, caddr_t asa, int *alen); }
-33 STD POSIX { int access(char *path, int flags); }
-34 STD BSD { int chflags(char *path, int flags); }
-35 STD BSD { int fchflags(int fd, int flags); }
-36 STD BSD { int sync(void); }
-37 MSTD POSIX { int kill(int pid, int signum); }
-38 COMPAT POSIX { int stat(char *path, struct ostat *ub); }
-39 MSTD POSIX { pid_t getppid(void); }
-40 COMPAT POSIX { int lstat(char *path, struct ostat *ub); }
-41 STD POSIX { int dup(u_int fd); }
-42 STD POSIX { int pipe(void); }
-43 MSTD POSIX { gid_t getegid(void); }
-44 MSTD BSD { int profil(caddr_t samples, size_t size, \
+30 MNOPROTO BSD { int accept(int s, caddr_t name, int *anamelen); }
+31 MNOPROTO BSD { int getpeername(int fdes, caddr_t asa, int *alen); }
+32 MNOPROTO BSD { int getsockname(int fdes, caddr_t asa, int *alen); }
+33 STD POSIX { int ia32_access(char *path, int flags); }
+34 STD BSD { int ia32_chflags(char *path, int flags); }
+35 NOPROTO BSD { int fchflags(int fd, int flags); }
+36 NOPROTO BSD { int sync(void); }
+37 MNOPROTO POSIX { int kill(int pid, int signum); }
+38 UNIMPL POSIX ostat
+39 MNOPROTO POSIX { pid_t getppid(void); }
+40 UNIMPL POSIX olstat
+41 NOPROTO POSIX { int dup(u_int fd); }
+42 NOPROTO POSIX { int pipe(void); }
+43 MNOPROTO POSIX { gid_t getegid(void); }
+44 MNOPROTO BSD { int profil(caddr_t samples, size_t size, \
size_t offset, u_int scale); }
-45 STD BSD { int ktrace(const char *fname, int ops, int facs, \
+45 NOPROTO BSD { int ktrace(const char *fname, int ops, int facs, \
int pid); }
-46 MCOMPAT POSIX { int sigaction(int signum, struct osigaction *nsa, \
- struct osigaction *osa); }
-47 MSTD POSIX { gid_t getgid(void); }
-48 MCOMPAT POSIX { int sigprocmask(int how, osigset_t mask); }
-; XXX note nonstandard (bogus) calling convention - the libc stub passes
-; us the mask, not a pointer to it, and we return the old mask as the
-; (int) return value.
-49 MSTD BSD { int getlogin(char *namebuf, u_int namelen); }
-50 MSTD BSD { int setlogin(char *namebuf); }
-51 MSTD BSD { int acct(char *path); }
-52 MCOMPAT POSIX { int sigpending(void); }
-53 MSTD BSD { int sigaltstack(stack_t *ss, stack_t *oss); }
-54 MSTD POSIX { int ioctl(int fd, u_long com, caddr_t data); }
-55 MSTD BSD { int reboot(int opt); }
-56 STD POSIX { int revoke(char *path); }
-57 STD POSIX { int symlink(char *path, char *link); }
-58 STD POSIX { int readlink(char *path, char *buf, int count); }
-59 MSTD POSIX { int execve(char *fname, char **argv, char **envv); }
-60 MSTD POSIX { int umask(int newmask); } umask umask_args int
-61 STD BSD { int chroot(char *path); }
-62 MCOMPAT POSIX { int fstat(int fd, struct ostat *sb); }
-63 MCOMPAT BSD { int getkerninfo(int op, char *where, size_t *size, \
- int arg); } getkerninfo getkerninfo_args int
-64 MCOMPAT BSD { int getpagesize(void); } \
- getpagesize getpagesize_args int
-65 STD BSD { int msync(void *addr, size_t len, int flags); }
-66 MSTD BSD { int vfork(void); }
+46 UNIMPL POSIX osigaction
+47 MNOPROTO POSIX { gid_t getgid(void); }
+48 UNIMPL POSIX osigprocmask
+49 MNOPROTO BSD { int getlogin(char *namebuf, u_int namelen); }
+50 MNOPROTO BSD { int setlogin(char *namebuf); }
+51 MNOPROTO BSD { int acct(char *path); }
+52 MNOPROTO POSIX { int sigpending(void); }
+53 STD BSD { int ia32_sigaltstack(struct sigaltstack32 *ss, struct sigaltstack32 *oss); }
+54 MNOPROTO POSIX { int ioctl(int fd, u_long com, caddr_t data); }
+55 MNOPROTO BSD { int reboot(int opt); }
+56 NOPROTO POSIX { int revoke(char *path); }
+57 NOPROTO POSIX { int symlink(char *path, char *link); }
+58 NOPROTO POSIX { int readlink(char *path, char *buf, int count); }
+59 STD POSIX { int ia32_execve(char *fname, u_int32_t *argv, u_int32_t *envv); }
+60 MNOPROTO POSIX { int umask(int newmask); } umask umask_args int
+61 NOPROTO BSD { int chroot(char *path); }
+62 OBSOL POSIX ofstat
+63 OBSOL BSD ogetkerninfo
+64 OBSOL BSD ogetpagesize
+65 OBSOL BSD omsync
+66 OBSOL BSD ovfork
67 OBSOL NOHIDE vread
68 OBSOL NOHIDE vwrite
-69 MSTD BSD { int sbrk(int incr); }
-70 MSTD BSD { int sstk(int incr); }
-71 MCOMPAT BSD { int mmap(void *addr, int len, int prot, \
- int flags, int fd, long pos); }
-72 MSTD BSD { int ovadvise(int anom); } vadvise ovadvise_args int
-73 MSTD BSD { int munmap(void *addr, size_t len); }
-74 MSTD BSD { int mprotect(const void *addr, size_t len, int prot); }
-75 MSTD BSD { int madvise(void *addr, size_t len, int behav); }
+69 MNOPROTO BSD { int sbrk(int incr); }
+70 MNOPROTO BSD { int sstk(int incr); }
+71 OBSOL BSD ommap
+72 MNOPROTO BSD { int ovadvise(int anom); } vadvise ovadvise_args int
+73 MNOPROTO BSD { int munmap(void *addr, size_t len); }
+74 MNOPROTO BSD { int mprotect(const void *addr, size_t len, int prot); }
+75 MNOPROTO BSD { int madvise(void *addr, size_t len, int behav); }
76 OBSOL NOHIDE vhangup
77 OBSOL NOHIDE vlimit
-78 MSTD BSD { int mincore(const void *addr, size_t len, \
+78 MNOPROTO BSD { int mincore(const void *addr, size_t len, \
char *vec); }
-79 MSTD POSIX { int getgroups(u_int gidsetsize, gid_t *gidset); }
-80 MSTD POSIX { int setgroups(u_int gidsetsize, gid_t *gidset); }
-81 MSTD POSIX { int getpgrp(void); }
-82 MSTD POSIX { int setpgid(int pid, int pgid); }
-83 MSTD BSD { int setitimer(u_int which, struct itimerval *itv, \
- struct itimerval *oitv); }
-84 MCOMPAT BSD { int wait(void); }
-85 MSTD BSD { int swapon(char *name); }
-86 MSTD BSD { int getitimer(u_int which, struct itimerval *itv); }
-87 MCOMPAT BSD { int gethostname(char *hostname, u_int len); } \
- gethostname gethostname_args int
-88 MCOMPAT BSD { int sethostname(char *hostname, u_int len); } \
- sethostname sethostname_args int
-89 MSTD BSD { int getdtablesize(void); }
-90 MSTD POSIX { int dup2(u_int from, u_int to); }
+79 MNOPROTO POSIX { int getgroups(u_int gidsetsize, gid_t *gidset); }
+80 MNOPROTO POSIX { int setgroups(u_int gidsetsize, gid_t *gidset); }
+81 MNOPROTO POSIX { int getpgrp(void); }
+82 MNOPROTO POSIX { int setpgid(int pid, int pgid); }
+83 STD BSD { int ia32_setitimer(u_int which, \
+ struct itimerval32 *itv, \
+ struct itimerval32 *oitv); }
+84 OBSOL BSD owait
+85 OBSOL BSD oswapon
+86 OBSOL BSD ogetitimer
+87 OBSOL BSD ogethostname
+88 OBSOL BSD osethostname
+89 MNOPROTO BSD { int getdtablesize(void); }
+90 MNOPROTO POSIX { int dup2(u_int from, u_int to); }
91 UNIMPL BSD getdopt
-92 MSTD POSIX { int fcntl(int fd, int cmd, long arg); }
+92 MNOPROTO POSIX { int fcntl(int fd, int cmd, long arg); }
; XXX should be { int fcntl(int fd, int cmd, ...); }
; but we're not ready for varargs.
; XXX man page says `int arg' too.
-93 MSTD BSD { int select(int nd, fd_set *in, fd_set *ou, \
- fd_set *ex, struct timeval *tv); }
+93 STD BSD { int ia32_select(int nd, fd_set *in, fd_set *ou, \
+ fd_set *ex, struct timeval32 *tv); }
+; XXX need to override for big-endian - little-endian should work fine.
94 UNIMPL BSD setdopt
-95 STD POSIX { int fsync(int fd); }
-96 MSTD BSD { int setpriority(int which, int who, int prio); }
-97 MSTD BSD { int socket(int domain, int type, int protocol); }
-98 MSTD BSD { int connect(int s, caddr_t name, int namelen); }
-99 MCPT_NOA BSD { int accept(int s, caddr_t name, int *anamelen); } \
+95 NOPROTO POSIX { int fsync(int fd); }
+96 MNOPROTO BSD { int setpriority(int which, int who, int prio); }
+97 MNOPROTO BSD { int socket(int domain, int type, int protocol); }
+98 MNOPROTO BSD { int connect(int s, caddr_t name, int namelen); }
+99 MNOPROTO BSD { int accept(int s, caddr_t name, int *anamelen); } \
accept accept_args int
-100 MSTD BSD { int getpriority(int which, int who); }
-101 MCOMPAT BSD { int send(int s, caddr_t buf, int len, int flags); }
-102 MCOMPAT BSD { int recv(int s, caddr_t buf, int len, int flags); }
-103 STD BSD { int osigreturn(struct osigcontext *sigcntxp); }
-104 MSTD BSD { int bind(int s, caddr_t name, int namelen); }
-105 MSTD BSD { int setsockopt(int s, int level, int name, \
+100 MNOPROTO BSD { int getpriority(int which, int who); }
+101 OBSOL BSD osend
+102 OBSOL BSD orecv
+103 OBSOL BSD osigreturn
+104 MNOPROTO BSD { int bind(int s, caddr_t name, int namelen); }
+105 MNOPROTO BSD { int setsockopt(int s, int level, int name, \
caddr_t val, int valsize); }
-106 MSTD BSD { int listen(int s, int backlog); }
+106 MNOPROTO BSD { int listen(int s, int backlog); }
107 OBSOL NOHIDE vtimes
-108 MCOMPAT BSD { int sigvec(int signum, struct sigvec *nsv, \
- struct sigvec *osv); }
-109 MCOMPAT BSD { int sigblock(int mask); }
-110 MCOMPAT BSD { int sigsetmask(int mask); }
-111 MCOMPAT POSIX { int sigsuspend(osigset_t mask); }
-; XXX note nonstandard (bogus) calling convention - the libc stub passes
-; us the mask, not a pointer to it.
-112 MCOMPAT BSD { int sigstack(struct sigstack *nss, \
- struct sigstack *oss); }
-113 MCOMPAT BSD { int recvmsg(int s, struct omsghdr *msg, int flags); }
-114 MCOMPAT BSD { int sendmsg(int s, caddr_t msg, int flags); }
+108 OBSOL BSD osigvec
+109 OBSOL BSD osigblock
+110 OBSOL BSD osigsetmask
+111 OBSOL POSIX osigsuspend
+112 OBSOL BSD osigstack
+113 OBSOL BSD orecvmsg
+114 OBSOL BSD osendmsg
115 OBSOL NOHIDE vtrace
-116 MSTD BSD { int gettimeofday(struct timeval *tp, \
+116 STD BSD { int ia32_gettimeofday(struct timeval32 *tp, \
struct timezone *tzp); }
-117 MSTD BSD { int getrusage(int who, struct rusage *rusage); }
-118 MSTD BSD { int getsockopt(int s, int level, int name, \
+117 STD BSD { int ia32_getrusage(int who, struct rusage32 *rusage); }
+118 MNOPROTO BSD { int getsockopt(int s, int level, int name, \
caddr_t val, int *avalsize); }
119 UNIMPL NOHIDE resuba (BSD/OS 2.x)
-120 MSTD BSD { int readv(int fd, struct iovec *iovp, u_int iovcnt); }
-121 MSTD BSD { int writev(int fd, struct iovec *iovp, \
+120 STD BSD { int ia32_readv(int fd, struct iovec32 *iovp, u_int iovcnt); }
+121 STD BSD { int ia32_writev(int fd, struct iovec32 *iovp, \
u_int iovcnt); }
-122 MSTD BSD { int settimeofday(struct timeval *tv, \
+122 STD BSD { int ia32_settimeofday(struct timeval32 *tv, \
struct timezone *tzp); }
-123 STD BSD { int fchown(int fd, int uid, int gid); }
-124 STD BSD { int fchmod(int fd, int mode); }
-125 MCPT_NOA BSD { int recvfrom(int s, caddr_t buf, size_t len, \
+123 NOPROTO BSD { int fchown(int fd, int uid, int gid); }
+124 NOPROTO BSD { int fchmod(int fd, int mode); }
+125 MNOPROTO BSD { int recvfrom(int s, caddr_t buf, size_t len, \
int flags, caddr_t from, int *fromlenaddr); } \
recvfrom recvfrom_args int
-126 MSTD BSD { int setreuid(int ruid, int euid); }
-127 MSTD BSD { int setregid(int rgid, int egid); }
-128 STD POSIX { int rename(char *from, char *to); }
-129 COMPAT BSD { int truncate(char *path, long length); }
-130 COMPAT BSD { int ftruncate(int fd, long length); }
-131 MSTD BSD { int flock(int fd, int how); }
-132 STD POSIX { int mkfifo(char *path, int mode); }
-133 MSTD BSD { int sendto(int s, caddr_t buf, size_t len, \
+126 MNOPROTO BSD { int setreuid(int ruid, int euid); }
+127 MNOPROTO BSD { int setregid(int rgid, int egid); }
+128 NOPROTO POSIX { int rename(char *from, char *to); }
+129 OBSOL BSD otruncate
+130 OBSOL BSD ftruncate
+131 MNOPROTO BSD { int flock(int fd, int how); }
+132 NOPROTO POSIX { int mkfifo(char *path, int mode); }
+133 MNOPROTO BSD { int sendto(int s, caddr_t buf, size_t len, \
int flags, caddr_t to, int tolen); }
-134 MSTD BSD { int shutdown(int s, int how); }
-135 MSTD BSD { int socketpair(int domain, int type, int protocol, \
+134 MNOPROTO BSD { int shutdown(int s, int how); }
+135 MNOPROTO BSD { int socketpair(int domain, int type, int protocol, \
int *rsv); }
-136 STD POSIX { int mkdir(char *path, int mode); }
-137 STD POSIX { int rmdir(char *path); }
-138 STD BSD { int utimes(char *path, struct timeval *tptr); }
+136 NOPROTO POSIX { int mkdir(char *path, int mode); }
+137 NOPROTO POSIX { int rmdir(char *path); }
+138 STD BSD { int ia32_utimes(char *path, \
+ struct timeval32 *tptr); }
139 OBSOL NOHIDE 4.2 sigreturn
-140 MSTD BSD { int adjtime(struct timeval *delta, \
- struct timeval *olddelta); }
-141 MCOMPAT BSD { int getpeername(int fdes, caddr_t asa, int *alen); }
-142 MCOMPAT BSD { long gethostid(void); }
-143 MCOMPAT BSD { int sethostid(long hostid); }
-144 MCOMPAT BSD { int getrlimit(u_int which, struct orlimit *rlp); }
-145 MCOMPAT BSD { int setrlimit(u_int which, struct orlimit *rlp); }
-146 MCOMPAT BSD { int killpg(int pgid, int signum); }
-147 MSTD POSIX { int setsid(void); }
-148 STD BSD { int quotactl(char *path, int cmd, int uid, \
+140 STD BSD { int ia32_adjtime(struct timeval32 *delta, \
+ struct timeval32 *olddelta); }
+141 OBSOL BSD ogetpeername
+142 OBSOL BSD ogethostid
+143 OBSOL BSD sethostid
+144 OBSOL BSD getrlimit
+145 OBSOL BSD setrlimit
+146 OBSOL BSD killpg
+147 MNOPROTO POSIX { int setsid(void); }
+148 NOPROTO BSD { int quotactl(char *path, int cmd, int uid, \
caddr_t arg); }
-149 MCOMPAT BSD { int quota(void); }
-150 MCPT_NOA BSD { int getsockname(int fdec, caddr_t asa, int *alen); }\
- getsockname getsockname_args int
+149 OBSOL BSD oquota
+150 OBSOL BSD ogetsockname
; Syscalls 151-180 inclusive are reserved for vendor-specific
; system calls. (This includes various calls added for compatibity
@@ -247,136 +239,138 @@
153 UNIMPL NOHIDE asyncdaemon (BSD/OS 2.x)
154 UNIMPL NOHIDE nosys
; 155 is initialized by the NFS code, if present.
-155 MNOIMPL BSD { int nfssvc(int flag, caddr_t argp); }
-156 COMPAT BSD { int getdirentries(int fd, char *buf, u_int count, \
+155 UNIMPL NOHIDE nfssvc
+156 NOPROTO BSD { int getdirentries(int fd, char *buf, u_int count, \
long *basep); }
-157 STD BSD { int statfs(char *path, struct statfs *buf); }
-158 STD BSD { int fstatfs(int fd, struct statfs *buf); }
+157 STD BSD { int ia32_statfs(char *path, struct statfs32 *buf); }
+158 STD BSD { int ia32_fstatfs(int fd, struct statfs32 *buf); }
159 UNIMPL NOHIDE nosys
160 UNIMPL NOHIDE nosys
-161 STD BSD { int getfh(char *fname, struct fhandle *fhp); }
-162 MSTD BSD { int getdomainname(char *domainname, int len); }
-163 MSTD BSD { int setdomainname(char *domainname, int len); }
-164 MSTD BSD { int uname(struct utsname *name); }
-165 STD BSD { int sysarch(int op, char *parms); }
-166 MSTD BSD { int rtprio(int function, pid_t pid, \
+161 NOPROTO BSD { int getfh(char *fname, struct fhandle *fhp); }
+162 MNOPROTO BSD { int getdomainname(char *domainname, int len); }
+163 MNOPROTO BSD { int setdomainname(char *domainname, int len); }
+164 MNOPROTO BSD { int uname(struct utsname *name); }
+165 NOPROTO BSD { int sysarch(int op, char *parms); }
+166 MNOPROTO BSD { int rtprio(int function, pid_t pid, \
struct rtprio *rtp); }
167 UNIMPL NOHIDE nosys
168 UNIMPL NOHIDE nosys
-; 169 is initialized by the SYSVSEM code if present or loaded
-169 MNOSTD BSD { int semsys(int which, int a2, int a3, int a4, \
+169 STD BSD { int ia32_semsys(int which, int a2, int a3, int a4, \
int a5); }
-; 169 is initialized by the SYSVMSG code if present or loaded
-; XXX should be { int semsys(int which, ...); }
-170 MNOSTD BSD { int msgsys(int which, int a2, int a3, int a4, \
+170 STD BSD { int ia32_msgsys(int which, int a2, int a3, int a4, \
int a5, int a6); }
-; 169 is initialized by the SYSVSHM code if present or loaded
-; XXX should be { int msgsys(int which, ...); }
-171 MNOSTD BSD { int shmsys(int which, int a2, int a3, int a4); }
-; XXX should be { int shmsys(int which, ...); }
+171 STD BSD { int ia32_shmsys(int which, int a2, int a3, int a4); }
172 UNIMPL NOHIDE nosys
-173 MSTD POSIX { ssize_t pread(int fd, void *buf, size_t nbyte, \
- int pad, off_t offset); }
-174 MSTD POSIX { ssize_t pwrite(int fd, const void *buf, \
- size_t nbyte, int pad, off_t offset); }
+173 STD POSIX { ssize_t ia32_pread(int fd, void *buf, size_t nbyte, \
+ int pad, u_int32_t offsetlo, u_int32_t offsethi); }
+; XXX note - bigendian is different
+174 STD POSIX { ssize_t ia32_pwrite(int fd, const void *buf, \
+ size_t nbyte, int pad, u_int32_t offsetlo, \
+ u_int32_t offsethi); }
+; XXX note - bigendian is different
175 UNIMPL NOHIDE nosys
-176 MSTD BSD { int ntp_adjtime(struct timex *tp); }
+176 MNOPROTO BSD { int ntp_adjtime(struct timex *tp); }
177 UNIMPL NOHIDE sfork (BSD/OS 2.x)
178 UNIMPL NOHIDE getdescriptor (BSD/OS 2.x)
179 UNIMPL NOHIDE setdescriptor (BSD/OS 2.x)
180 UNIMPL NOHIDE nosys
; Syscalls 181-199 are used by/reserved for BSD
-181 MSTD POSIX { int setgid(gid_t gid); }
-182 MSTD BSD { int setegid(gid_t egid); }
-183 MSTD BSD { int seteuid(uid_t euid); }
+181 MNOPROTO POSIX { int setgid(gid_t gid); }
+182 MNOPROTO BSD { int setegid(gid_t egid); }
+183 MNOPROTO BSD { int seteuid(uid_t euid); }
184 UNIMPL BSD lfs_bmapv
185 UNIMPL BSD lfs_markv
186 UNIMPL BSD lfs_segclean
187 UNIMPL BSD lfs_segwait
-188 STD POSIX { int stat(char *path, struct stat *ub); }
-189 MSTD POSIX { int fstat(int fd, struct stat *sb); }
-190 STD POSIX { int lstat(char *path, struct stat *ub); }
-191 STD POSIX { int pathconf(char *path, int name); }
-192 MSTD POSIX { int fpathconf(int fd, int name); }
+188 STD POSIX { int ia32_stat(char *path, struct stat32 *ub); }
+189 STD POSIX { int ia32_fstat(int fd, struct stat32 *ub); }
+190 STD POSIX { int ia32_lstat(char *path, struct stat32 *ub); }
+191 NOPROTO POSIX { int pathconf(char *path, int name); }
+192 MNOPROTO POSIX { int fpathconf(int fd, int name); }
193 UNIMPL NOHIDE nosys
-194 MSTD BSD { int getrlimit(u_int which, \
+194 MNOPROTO BSD { int getrlimit(u_int which, \
struct rlimit *rlp); } \
getrlimit __getrlimit_args int
-195 MSTD BSD { int setrlimit(u_int which, \
+195 MNOPROTO BSD { int setrlimit(u_int which, \
struct rlimit *rlp); } \
setrlimit __setrlimit_args int
-196 STD BSD { int getdirentries(int fd, char *buf, u_int count, \
+196 NOPROTO BSD { int getdirentries(int fd, char *buf, u_int count, \
long *basep); }
-197 MSTD BSD { caddr_t mmap(caddr_t addr, size_t len, int prot, \
- int flags, int fd, int pad, off_t pos); }
-198 STD NOHIDE { int nosys(void); } __syscall __syscall_args int
-199 STD POSIX { off_t lseek(int fd, int pad, off_t offset, \
+197 STD BSD { caddr_t ia32_mmap(caddr_t addr, size_t len, \
+ int prot, int flags, int fd, int pad, \
+ u_int32_t poslo, u_int32_t poshi); }
+198 NOPROTO NOHIDE { int nosys(void); } __syscall __syscall_args int
+; XXX note - bigendian is different
+199 STD POSIX { off_t ia32_lseek(int fd, int pad, \
+ u_int32_t offsetlo, u_int32_t offsethi, \
int whence); }
-200 STD BSD { int truncate(char *path, int pad, off_t length); }
-201 STD BSD { int ftruncate(int fd, int pad, off_t length); }
-202 MSTD BSD { int __sysctl(int *name, u_int namelen, void *old, \
- size_t *oldlenp, void *new, size_t newlen); } \
- __sysctl sysctl_args int
-; properly, __sysctl should be a NOHIDE, but making an exception
-; here allows to avoid one in libc/sys/Makefile.inc.
-203 MSTD BSD { int mlock(const void *addr, size_t len); }
-204 MSTD BSD { int munlock(const void *addr, size_t len); }
-205 STD BSD { int undelete(char *path); }
-206 STD BSD { int futimes(int fd, struct timeval *tptr); }
-207 MSTD BSD { int getpgid(pid_t pid); }
+; XXX note - bigendian is different
+200 STD BSD { int ia32_truncate(char *path, int pad, \
+ u_int32_t lengthlo, u_int32_t lengthhi); }
+; XXX note - bigendian is different
+201 STD BSD { int ia32_ftruncate(int fd, int pad, \
+ u_int32_t lengthlo, u_int32_t lengthhi); }
+202 MSTD BSD { int ia32_sysctl(int *name, u_int namelen, \
+ void *old, u_int32_t *oldlenp, void *new, \
+ u_int32_t newlen); }
+203 MNOPROTO BSD { int mlock(const void *addr, size_t len); }
+204 MNOPROTO BSD { int munlock(const void *addr, size_t len); }
+205 NOPROTO BSD { int undelete(char *path); }
+206 NOPROTO BSD { int futimes(int fd, struct timeval *tptr); }
+207 MNOPROTO BSD { int getpgid(pid_t pid); }
208 UNIMPL NOHIDE newreboot (NetBSD)
-209 MSTD BSD { int poll(struct pollfd *fds, u_int nfds, \
+209 MNOPROTO BSD { int poll(struct pollfd *fds, u_int nfds, \
int timeout); }
;
; The following are reserved for loadable syscalls
;
-210 NODEF NOHIDE lkmnosys lkmnosys nosys_args int
-211 NODEF NOHIDE lkmnosys lkmnosys nosys_args int
-212 NODEF NOHIDE lkmnosys lkmnosys nosys_args int
-213 NODEF NOHIDE lkmnosys lkmnosys nosys_args int
-214 NODEF NOHIDE lkmnosys lkmnosys nosys_args int
-215 NODEF NOHIDE lkmnosys lkmnosys nosys_args int
-216 NODEF NOHIDE lkmnosys lkmnosys nosys_args int
-217 NODEF NOHIDE lkmnosys lkmnosys nosys_args int
-218 NODEF NOHIDE lkmnosys lkmnosys nosys_args int
-219 NODEF NOHIDE lkmnosys lkmnosys nosys_args int
+210 UNIMPL NOHIDE
+211 UNIMPL NOHIDE
+212 UNIMPL NOHIDE
+213 UNIMPL NOHIDE
+214 UNIMPL NOHIDE
+215 UNIMPL NOHIDE
+216 UNIMPL NOHIDE
+217 UNIMPL NOHIDE
+218 UNIMPL NOHIDE
+219 UNIMPL NOHIDE
;
; The following were introduced with NetBSD/4.4Lite-2
; They are initialized by thier respective modules/sysinits
-220 MNOSTD BSD { int __semctl(int semid, int semnum, int cmd, \
+220 MNOPROTO BSD { int __semctl(int semid, int semnum, int cmd, \
union semun *arg); }
-221 MNOSTD BSD { int semget(key_t key, int nsems, int semflg); }
-222 MNOSTD BSD { int semop(int semid, struct sembuf *sops, \
+221 MNOPROTO BSD { int semget(key_t key, int nsems, int semflg); }
+222 MNOPROTO BSD { int semop(int semid, struct sembuf *sops, \
u_int nsops); }
223 UNIMPL NOHIDE semconfig
-224 MNOSTD BSD { int msgctl(int msqid, int cmd, \
+224 MNOPROTO BSD { int msgctl(int msqid, int cmd, \
struct msqid_ds *buf); }
-225 MNOSTD BSD { int msgget(key_t key, int msgflg); }
-226 MNOSTD BSD { int msgsnd(int msqid, void *msgp, size_t msgsz, \
+225 MNOPROTO BSD { int msgget(key_t key, int msgflg); }
+226 MNOPROTO BSD { int msgsnd(int msqid, void *msgp, size_t msgsz, \
int msgflg); }
-227 MNOSTD BSD { int msgrcv(int msqid, void *msgp, size_t msgsz, \
+227 MNOPROTO BSD { int msgrcv(int msqid, void *msgp, size_t msgsz, \
long msgtyp, int msgflg); }
-228 MNOSTD BSD { int shmat(int shmid, void *shmaddr, int shmflg); }
-229 MNOSTD BSD { int shmctl(int shmid, int cmd, \
+228 MNOPROTO BSD { int shmat(int shmid, void *shmaddr, int shmflg); }
+229 MNOPROTO BSD { int shmctl(int shmid, int cmd, \
struct shmid_ds *buf); }
-230 MNOSTD BSD { int shmdt(void *shmaddr); }
-231 MNOSTD BSD { int shmget(key_t key, int size, int shmflg); }
+230 MNOPROTO BSD { int shmdt(void *shmaddr); }
+231 MNOPROTO BSD { int shmget(key_t key, int size, int shmflg); }
;
-232 MSTD POSIX { int clock_gettime(clockid_t clock_id, \
+232 MNOPROTO POSIX { int clock_gettime(clockid_t clock_id, \
struct timespec *tp); }
-233 MSTD POSIX { int clock_settime(clockid_t clock_id, \
+233 MNOPROTO POSIX { int clock_settime(clockid_t clock_id, \
const struct timespec *tp); }
-234 MSTD POSIX { int clock_getres(clockid_t clock_id, \
+234 MNOPROTO POSIX { int clock_getres(clockid_t clock_id, \
struct timespec *tp); }
235 UNIMPL NOHIDE timer_create
236 UNIMPL NOHIDE timer_delete
237 UNIMPL NOHIDE timer_settime
238 UNIMPL NOHIDE timer_gettime
239 UNIMPL NOHIDE timer_getoverrun
-240 MSTD POSIX { int nanosleep(const struct timespec *rqtp, \
+240 MNOPROTO POSIX { int nanosleep(const struct timespec *rqtp, \
struct timespec *rmtp); }
241 UNIMPL NOHIDE nosys
242 UNIMPL NOHIDE nosys
@@ -388,12 +382,12 @@
248 UNIMPL NOHIDE nosys
249 UNIMPL NOHIDE nosys
; syscall numbers initially used in OpenBSD
-250 MSTD BSD { int minherit(void *addr, size_t len, int inherit); }
-251 MSTD BSD { int rfork(int flags); }
-252 MSTD BSD { int openbsd_poll(struct pollfd *fds, u_int nfds, \
+250 MNOPROTO BSD { int minherit(void *addr, size_t len, int inherit); }
+251 MNOPROTO BSD { int rfork(int flags); }
+252 MNOPROTO BSD { int openbsd_poll(struct pollfd *fds, u_int nfds, \
int timeout); }
-253 STD BSD { int issetugid(void); }
-254 STD BSD { int lchown(char *path, int uid, int gid); }
+253 NOPROTO BSD { int issetugid(void); }
+254 NOPROTO BSD { int lchown(char *path, int uid, int gid); }
255 UNIMPL NOHIDE nosys
256 UNIMPL NOHIDE nosys
257 UNIMPL NOHIDE nosys
@@ -411,15 +405,15 @@
269 UNIMPL NOHIDE nosys
270 UNIMPL NOHIDE nosys
271 UNIMPL NOHIDE nosys
-272 STD BSD { int getdents(int fd, char *buf, size_t count); }
+272 NOPROTO BSD { int getdents(int fd, char *buf, size_t count); }
273 UNIMPL NOHIDE nosys
-274 STD BSD { int lchmod(char *path, mode_t mode); }
+274 NOPROTO BSD { int lchmod(char *path, mode_t mode); }
275 NOPROTO BSD { int lchown(char *path, uid_t uid, gid_t gid); } netbsd_lchown lchown_args int
-276 STD BSD { int lutimes(char *path, struct timeval *tptr); }
+276 NOPROTO BSD { int lutimes(char *path, struct timeval *tptr); }
277 MNOPROTO BSD { int msync(void *addr, size_t len, int flags); } netbsd_msync msync_args int
-278 STD BSD { int nstat(char *path, struct nstat *ub); }
-279 MSTD BSD { int nfstat(int fd, struct nstat *sb); }
-280 STD BSD { int nlstat(char *path, struct nstat *ub); }
+278 NOPROTO BSD { int nstat(char *path, struct nstat *ub); }
+279 MNOPROTO BSD { int nfstat(int fd, struct nstat *sb); }
+280 NOPROTO BSD { int nlstat(char *path, struct nstat *ub); }
281 UNIMPL NOHIDE nosys
282 UNIMPL NOHIDE nosys
283 UNIMPL NOHIDE nosys
@@ -437,126 +431,133 @@
295 UNIMPL NOHIDE nosys
296 UNIMPL NOHIDE nosys
; XXX 297 is 300 in NetBSD
-297 STD BSD { int fhstatfs(const struct fhandle *u_fhp, struct statfs *buf); }
-298 STD BSD { int fhopen(const struct fhandle *u_fhp, int flags); }
-299 STD BSD { int fhstat(const struct fhandle *u_fhp, struct stat *sb); }
+297 NOPROTO BSD { int fhstatfs(const struct fhandle *u_fhp, struct statfs *buf); }
+298 NOPROTO BSD { int fhopen(const struct fhandle *u_fhp, int flags); }
+299 NOPROTO BSD { int fhstat(const struct fhandle *u_fhp, struct stat *sb); }
; syscall numbers for FreeBSD
-300 MSTD BSD { int modnext(int modid); }
-301 MSTD BSD { int modstat(int modid, struct module_stat* stat); }
-302 MSTD BSD { int modfnext(int modid); }
-303 MSTD BSD { int modfind(const char *name); }
-304 MSTD BSD { int kldload(const char *file); }
-305 MSTD BSD { int kldunload(int fileid); }
-306 MSTD BSD { int kldfind(const char *file); }
-307 MSTD BSD { int kldnext(int fileid); }
-308 MSTD BSD { int kldstat(int fileid, struct kld_file_stat* stat); }
-309 MSTD BSD { int kldfirstmod(int fileid); }
-310 MSTD BSD { int getsid(pid_t pid); }
-311 MSTD BSD { int setresuid(uid_t ruid, uid_t euid, uid_t suid); }
-312 MSTD BSD { int setresgid(gid_t rgid, gid_t egid, gid_t sgid); }
+300 MNOPROTO BSD { int modnext(int modid); }
+301 MNOPROTO BSD { int modstat(int modid, struct module_stat* stat); }
+302 MNOPROTO BSD { int modfnext(int modid); }
+303 MNOPROTO BSD { int modfind(const char *name); }
+304 MNOPROTO BSD { int kldload(const char *file); }
+305 MNOPROTO BSD { int kldunload(int fileid); }
+306 MNOPROTO BSD { int kldfind(const char *file); }
+307 MNOPROTO BSD { int kldnext(int fileid); }
+308 MNOPROTO BSD { int kldstat(int fileid, struct kld_file_stat* stat); }
+309 MNOPROTO BSD { int kldfirstmod(int fileid); }
+310 MNOPROTO BSD { int getsid(pid_t pid); }
+311 MNOPROTO BSD { int setresuid(uid_t ruid, uid_t euid, uid_t suid); }
+312 MNOPROTO BSD { int setresgid(gid_t rgid, gid_t egid, gid_t sgid); }
313 OBSOL NOHIDE signanosleep
-314 NOSTD BSD { int aio_return(struct aiocb *aiocbp); }
-315 NOSTD BSD { int aio_suspend(struct aiocb * const * aiocbp, int nent, const struct timespec *timeout); }
-316 NOSTD BSD { int aio_cancel(int fd, struct aiocb *aiocbp); }
-317 NOSTD BSD { int aio_error(struct aiocb *aiocbp); }
-318 NOSTD BSD { int aio_read(struct aiocb *aiocbp); }
-319 NOSTD BSD { int aio_write(struct aiocb *aiocbp); }
-320 NOSTD BSD { int lio_listio(int mode, struct aiocb * const *acb_list, int nent, struct sigevent *sig); }
-321 MSTD BSD { int yield(void); }
+314 UNIMPL NOHIDE aio_return
+315 UNIMPL NOHIDE aio_suspend
+316 UNIMPL NOHIDE aio_cancel
+317 UNIMPL NOHIDE aio_error
+318 UNIMPL NOHIDE aio_read
+319 UNIMPL NOHIDE aio_write
+320 UNIMPL NOHIDE lio_listio
+321 MNOPROTO BSD { int yield(void); }
322 OBSOL NOHIDE thr_sleep
323 OBSOL NOHIDE thr_wakeup
-324 MSTD BSD { int mlockall(int how); }
-325 MSTD BSD { int munlockall(void); }
-326 STD BSD { int __getcwd(u_char *buf, u_int buflen); }
+324 MNOPROTO BSD { int mlockall(int how); }
+325 MNOPROTO BSD { int munlockall(void); }
+326 NOPROTO BSD { int __getcwd(u_char *buf, u_int buflen); }
-327 MSTD POSIX { int sched_setparam (pid_t pid, const struct sched_param *param); }
-328 MSTD POSIX { int sched_getparam (pid_t pid, struct sched_param *param); }
+327 MNOPROTO POSIX { int sched_setparam (pid_t pid, const struct sched_param *param); }
+328 MNOPROTO POSIX { int sched_getparam (pid_t pid, struct sched_param *param); }
-329 MSTD POSIX { int sched_setscheduler (pid_t pid, int policy, const struct sched_param *param); }
-330 MSTD POSIX { int sched_getscheduler (pid_t pid); }
+329 MNOPROTO POSIX { int sched_setscheduler (pid_t pid, int policy, const struct sched_param *param); }
+330 MNOPROTO POSIX { int sched_getscheduler (pid_t pid); }
-331 MSTD POSIX { int sched_yield (void); }
-332 MSTD POSIX { int sched_get_priority_max (int policy); }
-333 MSTD POSIX { int sched_get_priority_min (int policy); }
-334 MSTD POSIX { int sched_rr_get_interval (pid_t pid, struct timespec *interval); }
-335 STD BSD { int utrace(const void *addr, size_t len); }
-336 MSTD BSD { int sendfile(int fd, int s, off_t offset, size_t nbytes, \
- struct sf_hdtr *hdtr, off_t *sbytes, int flags); }
-337 STD BSD { int kldsym(int fileid, int cmd, void *data); }
-338 MSTD BSD { int jail(struct jail *jail); }
+331 MNOPROTO POSIX { int sched_yield (void); }
+332 MNOPROTO POSIX { int sched_get_priority_max (int policy); }
+333 MNOPROTO POSIX { int sched_get_priority_min (int policy); }
+334 MNOPROTO POSIX { int sched_rr_get_interval (pid_t pid, struct timespec *interval); }
+335 NOPROTO BSD { int utrace(const void *addr, size_t len); }
+; XXX note - bigendian is different
+336 MSTD BSD { int ia32_sendfile(int fd, int s, u_int32_t offsetlo, \
+ u_int32_t offsethi, size_t nbytes, \
+ struct sf_hdtr *hdtr, off_t *sbytes, int flags); }
+337 NOPROTO BSD { int kldsym(int fileid, int cmd, void *data); }
+338 MNOPROTO BSD { int jail(struct jail *jail); }
339 UNIMPL BSD pioctl
-340 MSTD POSIX { int sigprocmask(int how, const sigset_t *set, \
+340 MNOPROTO POSIX { int sigprocmask(int how, const sigset_t *set, \
sigset_t *oset); }
-341 MSTD POSIX { int sigsuspend(const sigset_t *sigmask); }
-342 MSTD POSIX { int sigaction(int sig, const struct sigaction *act, \
- struct sigaction *oact); }
-343 MSTD POSIX { int sigpending(sigset_t *set); }
-344 STD BSD { int sigreturn(const struct __ucontext *sigcntxp); }
+341 MNOPROTO POSIX { int sigsuspend(const sigset_t *sigmask); }
+342 STD POSIX { int ia32_sigaction(int sig, \
+ struct sigaction32 *act, \
+ struct sigaction32 *oact); }
+343 MNOPROTO POSIX { int sigpending(sigset_t *set); }
+344 MNOPROTO BSD { int sigreturn(const struct __ucontext *sigcntxp); }
345 UNIMPL NOHIDE sigtimedwait
346 UNIMPL NOHIDE sigwaitinfo
-347 MSTD BSD { int __acl_get_file(const char *path, \
+347 MNOPROTO BSD { int __acl_get_file(const char *path, \
acl_type_t type, struct acl *aclp); }
-348 MSTD BSD { int __acl_set_file(const char *path, \
+348 MNOPROTO BSD { int __acl_set_file(const char *path, \
acl_type_t type, struct acl *aclp); }
-349 MSTD BSD { int __acl_get_fd(int filedes, acl_type_t type, \
+349 MNOPROTO BSD { int __acl_get_fd(int filedes, acl_type_t type, \
struct acl *aclp); }
-350 MSTD BSD { int __acl_set_fd(int filedes, acl_type_t type, \
+350 MNOPROTO BSD { int __acl_set_fd(int filedes, acl_type_t type, \
struct acl *aclp); }
-351 MSTD BSD { int __acl_delete_file(const char *path, \
+351 MNOPROTO BSD { int __acl_delete_file(const char *path, \
acl_type_t type); }
-352 MSTD BSD { int __acl_delete_fd(int filedes, acl_type_t type); }
-353 MSTD BSD { int __acl_aclcheck_file(const char *path, \
+352 MNOPROTO BSD { int __acl_delete_fd(int filedes, acl_type_t type); }
+353 MNOPROTO BSD { int __acl_aclcheck_file(const char *path, \
acl_type_t type, struct acl *aclp); }
-354 MSTD BSD { int __acl_aclcheck_fd(int filedes, acl_type_t type, \
+354 MNOPROTO BSD { int __acl_aclcheck_fd(int filedes, acl_type_t type, \
struct acl *aclp); }
-355 STD BSD { int extattrctl(const char *path, int cmd, \
+355 NOPROTO BSD { int extattrctl(const char *path, int cmd, \
const char *filename, int attrnamespace, \
const char *attrname); }
-356 STD BSD { int extattr_set_file(const char *path, \
+356 NOPROTO BSD { int extattr_set_file(const char *path, \
int attrnamespace, const char *attrname, \
void *data, size_t nbytes); }
-357 STD BSD { ssize_t extattr_get_file(const char *path, \
+357 NOPROTO BSD { ssize_t extattr_get_file(const char *path, \
int attrnamespace, const char *attrname, \
void *data, size_t nbytes); }
-358 STD BSD { int extattr_delete_file(const char *path, \
+358 NOPROTO BSD { int extattr_delete_file(const char *path, \
int attrnamespace, const char *attrname); }
-359 NOSTD BSD { int aio_waitcomplete(struct aiocb **aiocbp, struct timespec *timeout); }
-360 MSTD BSD { int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); }
-361 MSTD BSD { int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); }
-362 MSTD BSD { int kqueue(void); }
-363 MSTD BSD { int kevent(int fd, \
+359 UNIMPL NOHIDE aio_waitcomplete
+360 MNOPROTO BSD { int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); }
+361 MNOPROTO BSD { int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); }
+362 MNOPROTO BSD { int kqueue(void); }
+363 MNOPROTO BSD { int kevent(int fd, \
const struct kevent *changelist, int nchanges, \
struct kevent *eventlist, int nevents, \
const struct timespec *timeout); }
-364 STD BSD { int __cap_get_proc(struct cap *cap_p); }
-365 STD BSD { int __cap_set_proc(struct cap *cap_p); }
-366 STD BSD { int __cap_get_fd(int fd, struct cap *cap_p); }
-367 STD BSD { int __cap_get_file(const char *path_p, struct cap *cap_p); }
-368 STD BSD { int __cap_set_fd(int fd, struct cap *cap_p); }
-369 STD BSD { int __cap_set_file(const char *path_p, struct cap *cap_p); }
-370 NODEF NOHIDE lkmressys lkmressys nosys_args int
-371 STD BSD { int extattr_set_fd(int fd, int attrnamespace, \
+364 UNIMPL NOHIDE __cap_get_proc
+365 UNIMPL NOHIDE __cap_set_proc
+366 UNIMPL NOHIDE __cap_get_fd
+367 UNIMPL NOHIDE __cap_get_file
+368 UNIMPL NOHIDE __cap_set_fd
+369 UNIMPL NOHIDE __cap_set_file
+370 UNIMPL NOHIDE lkmressys
+371 NOPROTO BSD { int extattr_set_fd(int fd, int attrnamespace, \
const char *attrname, void *data, \
size_t nbytes); }
-372 STD BSD { ssize_t extattr_get_fd(int fd, int attrnamespace, \
+372 NOPROTO BSD { ssize_t extattr_get_fd(int fd, int attrnamespace, \
const char *attrname, void *data, size_t nbytes); }
-373 STD BSD { int extattr_delete_fd(int fd, int attrnamespace, \
+373 NOPROTO BSD { int extattr_delete_fd(int fd, int attrnamespace, \
const char *attrname); }
-374 MSTD BSD { int __setugid(int flag); }
-375 NOIMPL BSD { int nfsclnt(int flag, caddr_t argp); }
-376 STD BSD { int eaccess(char *path, int flags); }
+374 MNOPROTO BSD { int __setugid(int flag); }
+375 UNIMPL BSD nfsclnt
+376 NOPROTO BSD { int eaccess(char *path, int flags); }
377 UNIMPL BSD afs_syscall
-378 STD BSD { int nmount(struct iovec *iovp, unsigned int iovcnt, \
+378 NOPROTO BSD { int nmount(struct iovec *iovp, unsigned int iovcnt, \
int flags); }
-379 STD BSD { int kse_exit(void); }
-380 STD BSD { int kse_wakeup(void); }
-381 STD BSD { int kse_new(struct kse_mailbox * mbx, \
+379 NOPROTO BSD { int kse_exit(void); }
+380 NOPROTO BSD { int kse_wakeup(void); }
+381 NOPROTO BSD { int kse_new(struct kse_mailbox * mbx, \
int new_grp_flag); }
-382 STD BSD { int thread_wakeup(struct thread_mailbox *tmbx); }
-383 STD BSD { int kse_yield(void); }
+382 NOPROTO BSD { int thread_wakeup(struct thread_mailbox *tmbx); }
+383 NOPROTO BSD { int kse_yield(void); }
384 UNIMPL BSD __mac_get_proc
385 UNIMPL BSD __mac_set_proc
386 UNIMPL BSD __mac_get_fd
387 UNIMPL BSD __mac_get_file
388 UNIMPL BSD __mac_set_fd
389 UNIMPL BSD __mac_set_file
+390 NOPROTO BSD { int kenv(int what, const char *name, char *value, \
+ int len); }
+391 NOPROTO BSD { int lchflags(const char *path, int flags); }
+392 NOPROTO BSD { int uuidgen(struct uuid *store, int count); }
diff --git a/sys/ia64/ia64/elf_machdep.c b/sys/ia64/ia64/elf_machdep.c
index dcee3a454739..320ce8081640 100644
--- a/sys/ia64/ia64/elf_machdep.c
+++ b/sys/ia64/ia64/elf_machdep.c
@@ -34,7 +34,45 @@
#include <sys/fcntl.h>
#include <sys/vnode.h>
#include <sys/linker.h>
+#include <sys/sysent.h>
+#include <sys/imgact_elf.h>
+#include <sys/syscall.h>
+#include <sys/signalvar.h>
#include <machine/elf.h>
+#include <machine/md_var.h>
+
+struct sysentvec elf64_freebsd_sysvec = {
+ SYS_MAXSYSCALL,
+ sysent,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ elf64_freebsd_fixup,
+ sendsig,
+ sigcode,
+ &szsigcode,
+ 0,
+ "FreeBSD ELF64",
+ __elfN(coredump),
+ NULL,
+ MINSIGSTKSZ
+};
+
+static Elf64_Brandinfo freebsd_brand_info = {
+ ELFOSABI_FREEBSD,
+ EM_IA_64,
+ "FreeBSD",
+ "",
+ "/usr/libexec/ld-elf.so.1",
+ &elf64_freebsd_sysvec
+ };
+
+SYSINIT(elf64, SI_SUB_EXEC, SI_ORDER_ANY,
+ (sysinit_cfunc_t) elf64_insert_brand_entry,
+ &freebsd_brand_info);
Elf_Addr link_elf_get_gp(linker_file_t);
diff --git a/sys/ia64/include/elf.h b/sys/ia64/include/elf.h
index 116029340528..7da070078c82 100644
--- a/sys/ia64/include/elf.h
+++ b/sys/ia64/include/elf.h
@@ -33,9 +33,13 @@
* ELF definitions for the IA-64 architecture.
*/
+#ifndef __ELF_WORD_SIZE
+#define __ELF_WORD_SIZE 64
+#endif
+
#include <sys/elf64.h> /* Definitions common to all 64 bit architectures. */
+#include <sys/elf32.h> /* Definitions common to all 32 bit architectures. */
-#define __ELF_WORD_SIZE 64 /* Used by <sys/elf_generic.h> */
#include <sys/elf_generic.h>
#define ELF_ARCH EM_IA_64
@@ -52,6 +56,13 @@
typedef struct { /* Auxiliary vector entry on initial stack */
int a_type; /* Entry type. */
union {
+ int a_val; /* Integer value. */
+ } a_un;
+} Elf32_Auxinfo;
+
+typedef struct { /* Auxiliary vector entry on initial stack */
+ int a_type; /* Entry type. */
+ union {
long a_val; /* Integer value. */
void *a_ptr; /* Address. */
void (*a_fcn)(void); /* Function pointer (not used). */
@@ -194,7 +205,11 @@ __ElfType(Auxinfo);
#define R_IA64_LDXMOV 0x87 /* immediate22 special */
/* Define "machine" characteristics */
+#if __ELF_WORD_SIZE == 32
+#define ELF_TARG_CLASS ELFCLASS32
+#else
#define ELF_TARG_CLASS ELFCLASS64
+#endif
#define ELF_TARG_DATA ELFDATA2LSB
#define ELF_TARG_MACH EM_IA_64
#define ELF_TARG_VER 1
diff --git a/sys/kern/imgact_aout.c b/sys/kern/imgact_aout.c
index 16629d11c2ae..b13837e8697c 100644
--- a/sys/kern/imgact_aout.c
+++ b/sys/kern/imgact_aout.c
@@ -178,7 +178,7 @@ exec_aout_imgact(imgp)
/*
* Destroy old process VM and create a new one (with a new stack)
*/
- exec_new_vmspace(imgp);
+ exec_new_vmspace(imgp, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS, USRSTACK);
/*
* The vm space can be changed by exec_new_vmspace
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index f2e1afce4bdf..1b350000243a 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -70,59 +70,30 @@
__ElfType(Brandinfo);
__ElfType(Auxargs);
-static int elf_check_header(const Elf_Ehdr *hdr);
-static int elf_freebsd_fixup(register_t **stack_base,
- struct image_params *imgp);
-static int elf_load_file(struct proc *p, const char *file, u_long *addr,
- u_long *entry);
-static int elf_load_section(struct proc *p,
+static int __elfN(check_header)(const Elf_Ehdr *hdr);
+static int __elfN(load_file)(struct proc *p, const char *file, u_long *addr,
+ u_long *entry, size_t pagesize);
+static int __elfN(load_section)(struct proc *p,
struct vmspace *vmspace, struct vnode *vp, vm_object_t object,
vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz,
- vm_prot_t prot);
-static int exec_elf_imgact(struct image_params *imgp);
+ vm_prot_t prot, size_t pagesize);
+static int __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp);
static int elf_trace = 0;
-SYSCTL_INT(_debug, OID_AUTO, elf_trace, CTLFLAG_RW, &elf_trace, 0, "");
-
-struct sysentvec elf_freebsd_sysvec = {
- SYS_MAXSYSCALL,
- sysent,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- elf_freebsd_fixup,
- sendsig,
- sigcode,
- &szsigcode,
- 0,
- "FreeBSD ELF",
- elf_coredump,
- NULL,
- MINSIGSTKSZ
-};
+#if __ELF_WORD_SIZE == 32
+SYSCTL_INT(_debug, OID_AUTO, elf32_trace, CTLFLAG_RW, &elf_trace, 0, "");
+#else
+SYSCTL_INT(_debug, OID_AUTO, elf64_trace, CTLFLAG_RW, &elf_trace, 0, "");
+#endif
-static Elf_Brandinfo freebsd_brand_info = {
- ELFOSABI_FREEBSD,
- "FreeBSD",
- "",
- "/usr/libexec/ld-elf.so.1",
- &elf_freebsd_sysvec
- };
-static Elf_Brandinfo *elf_brand_list[MAX_BRANDS] = {
- &freebsd_brand_info,
- NULL, NULL, NULL,
- NULL, NULL, NULL, NULL
- };
+static Elf_Brandinfo *elf_brand_list[MAX_BRANDS];
int
-elf_insert_brand_entry(Elf_Brandinfo *entry)
+__elfN(insert_brand_entry)(Elf_Brandinfo *entry)
{
int i;
- for (i=1; i<MAX_BRANDS; i++) {
+ for (i=0; i<MAX_BRANDS; i++) {
if (elf_brand_list[i] == NULL) {
elf_brand_list[i] = entry;
break;
@@ -134,11 +105,11 @@ elf_insert_brand_entry(Elf_Brandinfo *entry)
}
int
-elf_remove_brand_entry(Elf_Brandinfo *entry)
+__elfN(remove_brand_entry)(Elf_Brandinfo *entry)
{
int i;
- for (i=1; i<MAX_BRANDS; i++) {
+ for (i=0; i<MAX_BRANDS; i++) {
if (elf_brand_list[i] == entry) {
elf_brand_list[i] = NULL;
break;
@@ -150,7 +121,7 @@ elf_remove_brand_entry(Elf_Brandinfo *entry)
}
int
-elf_brand_inuse(Elf_Brandinfo *entry)
+__elfN(brand_inuse)(Elf_Brandinfo *entry)
{
struct proc *p;
int rval = FALSE;
@@ -168,25 +139,165 @@ elf_brand_inuse(Elf_Brandinfo *entry)
}
static int
-elf_check_header(const Elf_Ehdr *hdr)
+__elfN(check_header)(const Elf_Ehdr *hdr)
{
+ int i;
+
if (!IS_ELF(*hdr) ||
hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS ||
hdr->e_ident[EI_DATA] != ELF_TARG_DATA ||
hdr->e_ident[EI_VERSION] != EV_CURRENT)
return ENOEXEC;
- if (!ELF_MACHINE_OK(hdr->e_machine))
+ /*
+ * Make sure we have at least one brand for this machine.
+ */
+
+ for (i=0; i<MAX_BRANDS; i++) {
+ if (elf_brand_list[i]->machine == hdr->e_machine)
+ break;
+ }
+ if (i == MAX_BRANDS)
return ENOEXEC;
if (hdr->e_version != ELF_TARG_VER)
return ENOEXEC;
-
+
return 0;
}
static int
-elf_load_section(struct proc *p, struct vmspace *vmspace, struct vnode *vp, vm_object_t object, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot)
+__elfN(map_partial)(vm_map_t map, vm_object_t object, vm_ooffset_t offset,
+ vm_offset_t start, vm_offset_t end, vm_prot_t prot,
+ vm_prot_t max)
+{
+ int error, rv;
+ vm_offset_t off;
+ vm_offset_t data_buf = 0;
+
+ /*
+ * Create the page if it doesn't exist yet. Ignore errors.
+ */
+ vm_map_lock(map);
+ vm_map_insert(map, NULL, 0, trunc_page(start), round_page(end),
+ max, max, 0);
+ vm_map_unlock(map);
+
+ /*
+ * Find the page from the underlying object.
+ */
+ if (object) {
+ vm_object_reference(object);
+ rv = vm_map_find(exec_map,
+ object,
+ trunc_page(offset),
+ &data_buf,
+ PAGE_SIZE,
+ TRUE,
+ VM_PROT_READ,
+ VM_PROT_ALL,
+ MAP_COPY_ON_WRITE | MAP_PREFAULT_PARTIAL);
+ if (rv != KERN_SUCCESS) {
+ vm_object_deallocate(object);
+ return rv;
+ }
+
+ off = offset - trunc_page(offset);
+ error = copyout((caddr_t)data_buf+off, (caddr_t)start, end - start);
+ vm_map_remove(exec_map, data_buf, data_buf + PAGE_SIZE);
+ if (error) {
+ return KERN_FAILURE;
+ }
+ }
+
+ return KERN_SUCCESS;
+}
+
+static int
+__elfN(map_insert)(vm_map_t map, vm_object_t object, vm_ooffset_t offset,
+ vm_offset_t start, vm_offset_t end, vm_prot_t prot,
+ vm_prot_t max, int cow)
+{
+ int rv;
+
+ if (start != trunc_page(start)) {
+ rv = __elfN(map_partial)(map, object, offset,
+ start, round_page(start), prot, max);
+ if (rv)
+ return rv;
+ offset += round_page(start) - start;
+ start = round_page(start);
+ }
+ if (end != round_page(end)) {
+ rv = __elfN(map_partial)(map, object,
+ offset + trunc_page(end) - start,
+ trunc_page(end), end, prot, max);
+ if (rv)
+ return rv;
+ end = trunc_page(end);
+ }
+ if (end > start) {
+ if (offset & PAGE_MASK) {
+ vm_offset_t data_buf, off;
+ vm_size_t sz;
+ int error;
+
+ /*
+ * The mapping is not page aligned. This means we have
+ * to copy the data. Sigh.
+ */
+ rv = vm_map_find(map, 0, 0,
+ &start, end - start,
+ FALSE, prot, max, 0);
+ if (rv)
+ return rv;
+ while (start < end) {
+ vm_object_reference(object);
+ rv = vm_map_find(exec_map,
+ object,
+ trunc_page(offset),
+ &data_buf,
+ 2*PAGE_SIZE,
+ TRUE,
+ VM_PROT_READ,
+ VM_PROT_ALL,
+ (MAP_COPY_ON_WRITE
+ | MAP_PREFAULT_PARTIAL));
+ if (rv != KERN_SUCCESS) {
+ vm_object_deallocate(object);
+ return rv;
+ }
+ off = offset - trunc_page(offset);
+ sz = end - start;
+ if (sz > PAGE_SIZE)
+ sz = PAGE_SIZE;
+ error = copyout((caddr_t)data_buf+off,
+ (caddr_t)start, sz);
+ vm_map_remove(exec_map, data_buf,
+ data_buf + 2*PAGE_SIZE);
+ if (error) {
+ return KERN_FAILURE;
+ }
+ start += sz;
+ }
+ rv = KERN_SUCCESS;
+ } else {
+ vm_map_lock(map);
+ rv = vm_map_insert(map, object, offset, start, end,
+ prot, max, cow);
+ vm_map_unlock(map);
+ }
+ return rv;
+ } else {
+ return KERN_SUCCESS;
+ }
+}
+
+static int
+__elfN(load_section)(struct proc *p, struct vmspace *vmspace,
+ struct vnode *vp, vm_object_t object, vm_offset_t offset,
+ caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot,
+ size_t pagesize)
{
size_t map_len;
vm_offset_t map_addr;
@@ -214,8 +325,11 @@ elf_load_section(struct proc *p, struct vmspace *vmspace, struct vnode *vp, vm_o
return (ENOEXEC);
}
- map_addr = trunc_page((vm_offset_t)vmaddr);
- file_addr = trunc_page(offset);
+#define trunc_page_ps(va, ps) ((va) & ~(ps - 1))
+#define round_page_ps(va, ps) (((va) + (ps - 1)) & ~(ps - 1))
+
+ map_addr = trunc_page_ps((vm_offset_t)vmaddr, pagesize);
+ file_addr = trunc_page_ps(offset, pagesize);
/*
* We have two choices. We can either clear the data in the last page
@@ -224,14 +338,13 @@ elf_load_section(struct proc *p, struct vmspace *vmspace, struct vnode *vp, vm_o
* choose the second..
*/
if (memsz > filsz)
- map_len = trunc_page(offset+filsz) - file_addr;
+ map_len = trunc_page_ps(offset+filsz, pagesize) - file_addr;
else
- map_len = round_page(offset+filsz) - file_addr;
+ map_len = round_page_ps(offset+filsz, pagesize) - file_addr;
if (map_len != 0) {
vm_object_reference(object);
- vm_map_lock(&vmspace->vm_map);
- rv = vm_map_insert(&vmspace->vm_map,
+ rv = __elfN(map_insert)(&vmspace->vm_map,
object,
file_addr, /* file offset */
map_addr, /* virtual start */
@@ -239,7 +352,6 @@ elf_load_section(struct proc *p, struct vmspace *vmspace, struct vnode *vp, vm_o
prot,
VM_PROT_ALL,
MAP_COPY_ON_WRITE | MAP_PREFAULT);
- vm_map_unlock(&vmspace->vm_map);
if (rv != KERN_SUCCESS) {
vm_object_deallocate(object);
return EINVAL;
@@ -258,26 +370,25 @@ elf_load_section(struct proc *p, struct vmspace *vmspace, struct vnode *vp, vm_o
* segment in the file is extended to provide bss. It's a neat idea
* to try and save a page, but it's a pain in the behind to implement.
*/
- copy_len = (offset + filsz) - trunc_page(offset + filsz);
- map_addr = trunc_page((vm_offset_t)vmaddr + filsz);
- map_len = round_page((vm_offset_t)vmaddr + memsz) - map_addr;
+ copy_len = (offset + filsz) - trunc_page_ps(offset + filsz, pagesize);
+ map_addr = trunc_page_ps((vm_offset_t)vmaddr + filsz, pagesize);
+ map_len = round_page_ps((vm_offset_t)vmaddr + memsz, pagesize) - map_addr;
/* This had damn well better be true! */
- if (map_len != 0) {
- vm_map_lock(&vmspace->vm_map);
- rv = vm_map_insert(&vmspace->vm_map, NULL, 0,
- map_addr, map_addr + map_len,
- VM_PROT_ALL, VM_PROT_ALL, 0);
- vm_map_unlock(&vmspace->vm_map);
+ if (map_len != 0) {
+ rv = __elfN(map_insert)(&vmspace->vm_map, NULL, 0,
+ map_addr, map_addr + map_len,
+ VM_PROT_ALL, VM_PROT_ALL, 0);
if (rv != KERN_SUCCESS) {
- return EINVAL;
+ return EINVAL;
}
}
if (copy_len != 0) {
+ vm_offset_t off;
vm_object_reference(object);
rv = vm_map_find(exec_map,
- object,
+ object,
trunc_page(offset + filsz),
&data_buf,
PAGE_SIZE,
@@ -291,7 +402,10 @@ elf_load_section(struct proc *p, struct vmspace *vmspace, struct vnode *vp, vm_o
}
/* send the page fragment to user space */
- error = copyout((caddr_t)data_buf, (caddr_t)map_addr, copy_len);
+ off = trunc_page_ps(offset + filsz, pagesize)
+ - trunc_page(offset + filsz);
+ error = copyout((caddr_t)data_buf+off, (caddr_t)map_addr,
+ copy_len);
vm_map_remove(exec_map, data_buf, data_buf + PAGE_SIZE);
if (error) {
return (error);
@@ -299,10 +413,11 @@ elf_load_section(struct proc *p, struct vmspace *vmspace, struct vnode *vp, vm_o
}
/*
- * set it to the specified protection
+ * set it to the specified protection.
+ * XXX had better undo the damage from pasting over the cracks here!
*/
- vm_map_protect(&vmspace->vm_map, map_addr, map_addr + map_len, prot,
- FALSE);
+ vm_map_protect(&vmspace->vm_map, trunc_page(map_addr),
+ round_page(map_addr + map_len), prot, FALSE);
return error;
}
@@ -320,7 +435,8 @@ elf_load_section(struct proc *p, struct vmspace *vmspace, struct vnode *vp, vm_o
* the entry point for the loaded file.
*/
static int
-elf_load_file(struct proc *p, const char *file, u_long *addr, u_long *entry)
+__elfN(load_file)(struct proc *p, const char *file, u_long *addr,
+ u_long *entry, size_t pagesize)
{
struct {
struct nameidata nd;
@@ -363,8 +479,8 @@ elf_load_file(struct proc *p, const char *file, u_long *addr, u_long *entry)
}
/* XXXKSE */
- NDINIT(nd, LOOKUP, LOCKLEAF|FOLLOW, UIO_SYSSPACE, file, curthread);
-
+ NDINIT(nd, LOOKUP, LOCKLEAF|FOLLOW, UIO_SYSSPACE, file, curthread);
+
if ((error = namei(nd)) != 0) {
nd->ni_vp = NULL;
goto fail;
@@ -393,10 +509,10 @@ elf_load_file(struct proc *p, const char *file, u_long *addr, u_long *entry)
VOP_UNLOCK(nd->ni_vp, 0, curthread); /* XXXKSE */
if (error)
- goto fail;
+ goto fail;
hdr = (const Elf_Ehdr *)imgp->image_header;
- if ((error = elf_check_header(hdr)) != 0)
+ if ((error = __elfN(check_header)(hdr)) != 0)
goto fail;
if (hdr->e_type == ET_DYN)
rbase = *addr;
@@ -426,13 +542,14 @@ elf_load_file(struct proc *p, const char *file, u_long *addr, u_long *entry)
if (phdr[i].p_flags & PF_R)
prot |= VM_PROT_READ;
- if ((error = elf_load_section(p, vmspace, nd->ni_vp,
- imgp->object,
- phdr[i].p_offset,
- (caddr_t)phdr[i].p_vaddr +
- rbase,
- phdr[i].p_memsz,
- phdr[i].p_filesz, prot)) != 0)
+ if ((error = __elfN(load_section)
+ (p, vmspace, nd->ni_vp,
+ imgp->object,
+ phdr[i].p_offset,
+ (caddr_t)(uintptr_t)phdr[i].p_vaddr +
+ rbase,
+ phdr[i].p_memsz,
+ phdr[i].p_filesz, prot, pagesize)) != 0)
goto fail;
/*
* Establish the base address if this is the
@@ -463,20 +580,10 @@ fail:
return error;
}
-/*
- * non static, as it can be overridden by start_init()
- */
-#ifdef __ia64__
-int fallback_elf_brand = ELFOSABI_FREEBSD;
-#else
-int fallback_elf_brand = -1;
-#endif
-SYSCTL_INT(_kern, OID_AUTO, fallback_elf_brand, CTLFLAG_RW,
- &fallback_elf_brand, -1,
- "ELF brand of last resort");
+extern int fallback_elf_brand;
static int
-exec_elf_imgact(struct image_params *imgp)
+__CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
{
const Elf_Ehdr *hdr = (const Elf_Ehdr *) imgp->image_header;
const Elf_Phdr *phdr;
@@ -486,6 +593,7 @@ exec_elf_imgact(struct image_params *imgp)
u_long text_size = 0, data_size = 0;
u_long text_addr = 0, data_addr = 0;
u_long addr, entry = 0, proghdr = 0;
+ vm_offset_t maxuser, usrstack, pagesize;
int error, i;
const char *interp = NULL;
Elf_Brandinfo *brand_info;
@@ -496,7 +604,7 @@ exec_elf_imgact(struct image_params *imgp)
/*
* Do we have a valid ELF header ?
*/
- if (elf_check_header(hdr) != 0 || hdr->e_type != ET_EXEC)
+ if (__elfN(check_header)(hdr) != 0 || hdr->e_type != ET_EXEC)
return -1;
/*
@@ -510,7 +618,7 @@ exec_elf_imgact(struct image_params *imgp)
return ENOEXEC;
}
phdr = (const Elf_Phdr*)(imgp->image_header + hdr->e_phoff);
-
+
/*
* From this point on, we may have resources that need to be freed.
*/
@@ -528,7 +636,38 @@ exec_elf_imgact(struct image_params *imgp)
if ((error = exec_extract_strings(imgp)) != 0)
goto fail;
- exec_new_vmspace(imgp);
+ /*
+ * Tentatively identify the brand based on the machine so that
+ * we can figure out VM ranges and page sizes.
+ */
+ brand_info = NULL;
+ for (i = 0; i < MAX_BRANDS; i++) {
+ Elf_Brandinfo *bi = elf_brand_list[i];
+
+ if (bi != NULL &&
+ hdr->e_machine == bi->machine &&
+ (hdr->e_ident[EI_OSABI] == bi->brand
+ || 0 ==
+ strncmp((const char *)&hdr->e_ident[OLD_EI_BRAND],
+ bi->compat_3_brand, strlen(bi->compat_3_brand)))) {
+ brand_info = bi;
+ break;
+ }
+ }
+
+ pagesize = PAGE_SIZE;
+ maxuser = VM_MAXUSER_ADDRESS;
+ usrstack = USRSTACK;
+ if (brand_info) {
+ if (brand_info->sysvec->sv_pagesize)
+ pagesize = brand_info->sysvec->sv_pagesize;
+ if (brand_info->sysvec->sv_maxuser)
+ maxuser = brand_info->sysvec->sv_maxuser;
+ if (brand_info->sysvec->sv_usrstack)
+ usrstack = brand_info->sysvec->sv_usrstack;
+ }
+
+ exec_new_vmspace(imgp, VM_MIN_ADDRESS, maxuser, usrstack);
vmspace = imgp->proc->p_vmspace;
@@ -544,13 +683,23 @@ exec_elf_imgact(struct image_params *imgp)
if (phdr[i].p_flags & PF_R)
prot |= VM_PROT_READ;
- if ((error = elf_load_section(imgp->proc,
- vmspace, imgp->vp,
- imgp->object,
- phdr[i].p_offset,
- (caddr_t)phdr[i].p_vaddr,
- phdr[i].p_memsz,
- phdr[i].p_filesz, prot)) != 0)
+#if defined(__ia64__) && __ELF_WORD_SIZE == 32 && defined(IA32_ME_HARDER)
+ /*
+ * Some x86 binaries assume read == executable,
+ * notably the M3 runtime and therefore cvsup
+ */
+ if (prot & VM_PROT_READ)
+ prot |= VM_PROT_EXECUTE;
+#endif
+
+ if ((error = __elfN(load_section)
+ (imgp->proc,
+ vmspace, imgp->vp,
+ imgp->object,
+ phdr[i].p_offset,
+ (caddr_t)(uintptr_t)phdr[i].p_vaddr,
+ phdr[i].p_memsz,
+ phdr[i].p_filesz, prot, pagesize)) != 0)
goto fail;
/*
@@ -611,10 +760,11 @@ exec_elf_imgact(struct image_params *imgp)
for (i = 0; i < MAX_BRANDS; i++) {
Elf_Brandinfo *bi = elf_brand_list[i];
- if (bi != NULL &&
+ if (bi != NULL &&
+ hdr->e_machine == bi->machine &&
(hdr->e_ident[EI_OSABI] == bi->brand
- || 0 ==
- strncmp((const char *)&hdr->e_ident[OLD_EI_BRAND],
+ || 0 ==
+ strncmp((const char *)&hdr->e_ident[OLD_EI_BRAND],
bi->compat_3_brand, strlen(bi->compat_3_brand)))) {
brand_info = bi;
break;
@@ -628,6 +778,7 @@ exec_elf_imgact(struct image_params *imgp)
Elf_Brandinfo *bi = elf_brand_list[i];
if (bi != NULL &&
+ hdr->e_machine == bi->machine &&
strcmp(interp, bi->interp_path) == 0) {
brand_info = bi;
break;
@@ -640,7 +791,9 @@ exec_elf_imgact(struct image_params *imgp)
for (i = 0; i < MAX_BRANDS; i++) {
Elf_Brandinfo *bi = elf_brand_list[i];
- if (bi != NULL && fallback_elf_brand == bi->brand) {
+ if (bi != NULL &&
+ hdr->e_machine == bi->machine &&
+ fallback_elf_brand == bi->brand) {
brand_info = bi;
break;
}
@@ -657,17 +810,19 @@ exec_elf_imgact(struct image_params *imgp)
imgp->proc->p_sysent = brand_info->sysvec;
if (interp != NULL) {
path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
- snprintf(path, MAXPATHLEN, "%s%s",
+ snprintf(path, MAXPATHLEN, "%s%s",
brand_info->emul_path, interp);
- if ((error = elf_load_file(imgp->proc, path, &addr,
- &imgp->entry_addr)) != 0) {
- if ((error = elf_load_file(imgp->proc, interp, &addr,
- &imgp->entry_addr)) != 0) {
- uprintf("ELF interpreter %s not found\n", path);
+ if ((error = __elfN(load_file)(imgp->proc, path, &addr,
+ &imgp->entry_addr,
+ pagesize)) != 0) {
+ if ((error = __elfN(load_file)
+ (imgp->proc, interp, &addr,
+ &imgp->entry_addr, pagesize)) != 0) {
+ uprintf("ELF interpreter %s not found\n", path);
free(path, M_TEMP);
goto fail;
}
- }
+ }
free(path, M_TEMP);
}
@@ -692,13 +847,23 @@ fail:
return error;
}
-static int
-elf_freebsd_fixup(register_t **stack_base, struct image_params *imgp)
+#if __ELF_WORD_SIZE == 32
+#define suword suword32
+#define stacktype u_int32_t
+#else
+#define suword suword64
+#define stacktype u_int64_t
+#endif
+
+int
+__elfN(freebsd_fixup)(register_t **stack_base, struct image_params *imgp)
{
Elf_Auxargs *args = (Elf_Auxargs *)imgp->auxargs;
- register_t *pos;
+ stacktype *base;
+ stacktype *pos;
- pos = *stack_base + (imgp->argc + imgp->envc + 2);
+ base = (stacktype *)*stack_base;
+ pos = base + (imgp->argc + imgp->envc + 2);
if (args->trace) {
AUXARGS_ENTRY(pos, AT_DEBUG, 1);
@@ -718,10 +883,11 @@ elf_freebsd_fixup(register_t **stack_base, struct image_params *imgp)
free(imgp->auxargs, M_TEMP);
imgp->auxargs = NULL;
- (*stack_base)--;
- suword(*stack_base, (long) imgp->argc);
+ base--;
+ suword(base, (long) imgp->argc);
+ *stack_base = (register_t *)base;
return 0;
-}
+}
/*
* Code for generating ELF core dumps.
@@ -744,17 +910,17 @@ struct sseg_closure {
static void cb_put_phdr(vm_map_entry_t, void *);
static void cb_size_segment(vm_map_entry_t, void *);
static void each_writable_segment(struct proc *, segment_callback, void *);
-static int elf_corehdr(struct thread *, struct vnode *, struct ucred *,
+static int __elfN(corehdr)(struct thread *, struct vnode *, struct ucred *,
int, void *, size_t);
-static void elf_puthdr(struct proc *, void *, size_t *,
+static void __elfN(puthdr)(struct proc *, void *, size_t *,
const prstatus_t *, const prfpregset_t *, const prpsinfo_t *, int);
-static void elf_putnote(void *, size_t *, const char *, int,
+static void __elfN(putnote)(void *, size_t *, const char *, int,
const void *, size_t);
extern int osreldate;
int
-elf_coredump(td, vp, limit)
+__elfN(coredump)(td, vp, limit)
struct thread *td;
register struct vnode *vp;
off_t limit;
@@ -777,7 +943,7 @@ elf_coredump(td, vp, limit)
* size is calculated.
*/
hdrsize = 0;
- elf_puthdr((struct proc *)NULL, (void *)NULL, &hdrsize,
+ __elfN(puthdr)((struct proc *)NULL, (void *)NULL, &hdrsize,
(const prstatus_t *)NULL, (const prfpregset_t *)NULL,
(const prpsinfo_t *)NULL, seginfo.count);
@@ -792,7 +958,7 @@ elf_coredump(td, vp, limit)
if (hdr == NULL) {
return EINVAL;
}
- error = elf_corehdr(td, vp, cred, seginfo.count, hdr, hdrsize);
+ error = __elfN(corehdr)(td, vp, cred, seginfo.count, hdr, hdrsize);
/* Write the contents of all of the writable segments. */
if (error == 0) {
@@ -803,8 +969,8 @@ elf_coredump(td, vp, limit)
php = (Elf_Phdr *)((char *)hdr + sizeof(Elf_Ehdr)) + 1;
offset = hdrsize;
for (i = 0; i < seginfo.count; i++) {
- error = vn_rdwr_inchunks(UIO_WRITE, vp,
- (caddr_t)php->p_vaddr,
+ error = vn_rdwr_inchunks(UIO_WRITE, vp,
+ (caddr_t)(uintptr_t)php->p_vaddr,
php->p_filesz, offset, UIO_USERSPACE,
IO_UNIT | IO_DIRECT, cred, (int *)NULL, curthread); /* XXXKSE */
if (error != 0)
@@ -814,7 +980,7 @@ elf_coredump(td, vp, limit)
}
}
free(hdr, M_TEMP);
-
+
return error;
}
@@ -918,7 +1084,7 @@ each_writable_segment(p, func, closure)
* the page boundary.
*/
static int
-elf_corehdr(td, vp, cred, numsegs, hdr, hdrsize)
+__elfN(corehdr)(td, vp, cred, numsegs, hdr, hdrsize)
struct thread *td;
struct vnode *vp;
struct ucred *cred;
@@ -964,7 +1130,7 @@ elf_corehdr(td, vp, cred, numsegs, hdr, hdrsize)
/* Fill in the header. */
bzero(hdr, hdrsize);
off = 0;
- elf_puthdr(p, hdr, &off, status, fpregset, psinfo, numsegs);
+ __elfN(puthdr)(p, hdr, &off, status, fpregset, psinfo, numsegs);
free(tempdata, M_TEMP);
@@ -974,7 +1140,7 @@ elf_corehdr(td, vp, cred, numsegs, hdr, hdrsize)
}
static void
-elf_puthdr(struct proc *p, void *dst, size_t *off, const prstatus_t *status,
+__elfN(puthdr)(struct proc *p, void *dst, size_t *off, const prstatus_t *status,
const prfpregset_t *fpregset, const prpsinfo_t *psinfo, int numsegs)
{
size_t ehoff;
@@ -989,11 +1155,11 @@ elf_puthdr(struct proc *p, void *dst, size_t *off, const prstatus_t *status,
*off += (numsegs + 1) * sizeof(Elf_Phdr);
noteoff = *off;
- elf_putnote(dst, off, "FreeBSD", NT_PRSTATUS, status,
+ __elfN(putnote)(dst, off, "FreeBSD", NT_PRSTATUS, status,
sizeof *status);
- elf_putnote(dst, off, "FreeBSD", NT_FPREGSET, fpregset,
+ __elfN(putnote)(dst, off, "FreeBSD", NT_FPREGSET, fpregset,
sizeof *fpregset);
- elf_putnote(dst, off, "FreeBSD", NT_PRPSINFO, psinfo,
+ __elfN(putnote)(dst, off, "FreeBSD", NT_PRPSINFO, psinfo,
sizeof *psinfo);
notesz = *off - noteoff;
@@ -1056,7 +1222,7 @@ elf_puthdr(struct proc *p, void *dst, size_t *off, const prstatus_t *status,
}
static void
-elf_putnote(void *dst, size_t *off, const char *name, int type,
+__elfN(putnote)(void *dst, size_t *off, const char *name, int type,
const void *desc, size_t descsz)
{
Elf_Note note;
@@ -1078,5 +1244,10 @@ elf_putnote(void *dst, size_t *off, const char *name, int type,
/*
* Tell kern_execve.c about it, with a little help from the linker.
*/
-static struct execsw elf_execsw = {exec_elf_imgact, "ELF"};
-EXEC_SET(elf, elf_execsw);
+#if __ELF_WORD_SIZE == 32
+static struct execsw elf_execsw = {exec_elf32_imgact, "ELF32"};
+EXEC_SET(elf32, elf_execsw);
+#else
+static struct execsw elf_execsw = {exec_elf64_imgact, "ELF64"};
+EXEC_SET(elf64, elf_execsw);
+#endif
diff --git a/sys/kern/imgact_elf32.c b/sys/kern/imgact_elf32.c
new file mode 100644
index 000000000000..7fd99b7cceb4
--- /dev/null
+++ b/sys/kern/imgact_elf32.c
@@ -0,0 +1,38 @@
+/*-
+ * Copyright (c) 2002 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * There ought to be a better way of deciding this.
+ */
+#if defined(__i386__) || defined(__ia64__) || defined(__powerpc__)
+
+#define __ELF_WORD_SIZE 32
+
+#include <kern/imgact_elf.c>
+
+#endif
diff --git a/sys/kern/imgact_elf64.c b/sys/kern/imgact_elf64.c
new file mode 100644
index 000000000000..ea6d61d52755
--- /dev/null
+++ b/sys/kern/imgact_elf64.c
@@ -0,0 +1,38 @@
+/*-
+ * Copyright (c) 2002 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * There ought to be a better way of deciding this.
+ */
+#if defined(__alpha__) || defined(__ia64__) || defined(__sparc64__)
+
+#define __ELF_WORD_SIZE 64
+
+#include <kern/imgact_elf.c>
+
+#endif
diff --git a/sys/kern/imgact_elfN.c b/sys/kern/imgact_elfN.c
new file mode 100644
index 000000000000..fd8487fbfcdc
--- /dev/null
+++ b/sys/kern/imgact_elfN.c
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 2000 David O'Brien
+ * Copyright (c) 1995-1996 Søren Schmidt
+ * Copyright (c) 1996 Peter Wemm
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+
+#include <machine/elf.h>
+#include <sys/elf_generic.h>
+
+/*
+ * non static, as it can be overridden by start_init()
+ */
+#ifdef __ia64__
+int fallback_elf_brand = ELFOSABI_FREEBSD;
+#else
+int fallback_elf_brand = -1;
+#endif
+SYSCTL_INT(_kern, OID_AUTO, fallback_elf_brand, CTLFLAG_RW,
+ &fallback_elf_brand, -1,
+ "ELF brand of last resort");
+
diff --git a/sys/kern/imgact_gzip.c b/sys/kern/imgact_gzip.c
index 57a5c1d19f3a..3268413fd1e0 100644
--- a/sys/kern/imgact_gzip.c
+++ b/sys/kern/imgact_gzip.c
@@ -229,7 +229,7 @@ do_aout_hdr(struct imgact_gzip * gz)
/*
* Destroy old process VM and create a new one (with a new stack)
*/
- exec_new_vmspace(gz->ip);
+ exec_new_vmspace(gz->ip, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS, USRSTACK);
vmspace = gz->ip->proc->p_vmspace;
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index 6817bdc87a93..aa87a184ad3f 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -252,6 +252,9 @@ set_boot_verbose(void *data __unused)
}
SYSINIT(boot_verbose, SI_SUB_TUNABLES, SI_ORDER_ANY, set_boot_verbose, NULL)
+static struct sysentvec null_sysvec;
+
+
/*
***************************************************************************
****
@@ -317,11 +320,7 @@ proc0_init(void *dummy __unused)
session0.s_count = 1;
session0.s_leader = p;
-#ifdef __ELF__
- p->p_sysent = &elf_freebsd_sysvec;
-#else
- p->p_sysent = &aout_sysvec;
-#endif
+ p->p_sysent = &null_sysvec;
/*
* proc_linkup was already done in init_i386() or alphainit() etc.
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index c7df555dcef8..2ed383991037 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -284,7 +284,10 @@ interpret:
/*
* Copy out strings (args and env) and initialize stack base
*/
- stack_base = exec_copyout_strings(imgp);
+ if (p->p_sysent->sv_copyout_strings)
+ stack_base = (*p->p_sysent->sv_copyout_strings)(imgp);
+ else
+ stack_base = exec_copyout_strings(imgp);
/*
* If custom stack fixup routine present for this process
@@ -471,8 +474,12 @@ interpret:
p->p_args = NULL;
/* Set values passed into the program in registers. */
- setregs(td, imgp->entry_addr, (u_long)(uintptr_t)stack_base,
- imgp->ps_strings);
+ if (p->p_sysent->sv_setregs)
+ (*p->p_sysent->sv_setregs)(td, imgp->entry_addr,
+ (u_long)(uintptr_t)stack_base, imgp->ps_strings);
+ else
+ setregs(td, imgp->entry_addr, (u_long)(uintptr_t)stack_base,
+ imgp->ps_strings);
/* Cache arguments if they fit inside our allowance */
if (ps_arg_cache_limit >= i + sizeof(struct pargs)) {
@@ -628,17 +635,19 @@ exec_unmap_first_page(imgp)
* automatically in trap.c.
*/
int
-exec_new_vmspace(imgp)
+exec_new_vmspace(imgp, minuser, maxuser, stack_addr)
struct image_params *imgp;
+ vm_offset_t minuser, maxuser, stack_addr;
{
int error;
struct execlist *ep;
struct proc *p = imgp->proc;
struct vmspace *vmspace = p->p_vmspace;
- vm_offset_t stack_addr = USRSTACK - maxssiz;
GIANT_REQUIRED;
+ stack_addr = stack_addr - maxssiz;
+
imgp->vmspace_destroyed = 1;
/*
@@ -652,13 +661,15 @@ exec_new_vmspace(imgp)
* otherwise, create a new VM space so that other threads are
* not disrupted
*/
- if (vmspace->vm_refcnt == 1) {
+ if (vmspace->vm_refcnt == 1
+ && vm_map_min(&vmspace->vm_map) == minuser
+ && vm_map_max(&vmspace->vm_map) == maxuser) {
if (vmspace->vm_shm)
shmexit(p);
- pmap_remove_pages(vmspace_pmap(vmspace), 0, VM_MAXUSER_ADDRESS);
- vm_map_remove(&vmspace->vm_map, 0, VM_MAXUSER_ADDRESS);
+ pmap_remove_pages(vmspace_pmap(vmspace), minuser, maxuser);
+ vm_map_remove(&vmspace->vm_map, minuser, maxuser);
} else {
- vmspace_exec(p);
+ vmspace_exec(p, minuser, maxuser);
vmspace = p->p_vmspace;
}
diff --git a/sys/powerpc/powerpc/elf_machdep.c b/sys/powerpc/powerpc/elf_machdep.c
index 3a39ac6aa614..369af531ed84 100644
--- a/sys/powerpc/powerpc/elf_machdep.c
+++ b/sys/powerpc/powerpc/elf_machdep.c
@@ -32,9 +32,47 @@
#include <sys/proc.h>
#include <sys/namei.h>
#include <sys/fcntl.h>
+#include <sys/sysent.h>
+#include <sys/imgact_elf.h>
+#include <sys/syscall.h>
+#include <sys/signalvar.h>
#include <sys/vnode.h>
#include <sys/linker.h>
#include <machine/elf.h>
+#include <machine/md_var.h>
+
+struct sysentvec elf32_freebsd_sysvec = {
+ SYS_MAXSYSCALL,
+ sysent,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ elf32_freebsd_fixup,
+ sendsig,
+ sigcode,
+ &szsigcode,
+ 0,
+ "FreeBSD ELF32",
+ __elfN(coredump),
+ NULL,
+ MINSIGSTKSZ
+};
+
+static Elf32_Brandinfo freebsd_brand_info = {
+ ELFOSABI_FREEBSD,
+ EM_PPC,
+ "FreeBSD",
+ "",
+ "/usr/libexec/ld-elf.so.1",
+ &elf32_freebsd_sysvec
+ };
+
+SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_ANY,
+ (sysinit_cfunc_t) elf32_insert_brand_entry,
+ &freebsd_brand_info);
/* Process one elf relocation with addend. */
int
@@ -76,7 +114,7 @@ elf_reloc(linker_file_t lf, const void *data, int type)
addr = elf_lookup(lf, symidx, 1);
if (addr == 0)
return -1;
- addr += addend;
+ addr += addend;
if (*where != addr)
*where = addr;
break;
diff --git a/sys/sparc64/sparc64/elf_machdep.c b/sys/sparc64/sparc64/elf_machdep.c
index 158d12fb65be..21717fcc9fca 100644
--- a/sys/sparc64/sparc64/elf_machdep.c
+++ b/sys/sparc64/sparc64/elf_machdep.c
@@ -40,12 +40,52 @@
*/
#include <sys/param.h>
+#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/linker.h>
+#include <sys/sysent.h>
+#include <sys/imgact_elf.h>
+#include <sys/syscall.h>
+#include <sys/signalvar.h>
+#include <sys/vnode.h>
#include <machine/elf.h>
+#include <machine/md_var.h>
#include "linker_if.h"
+struct sysentvec elf64_freebsd_sysvec = {
+ SYS_MAXSYSCALL,
+ sysent,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ elf64_freebsd_fixup,
+ sendsig,
+ sigcode,
+ &szsigcode,
+ 0,
+ "FreeBSD ELF64",
+ __elfN(coredump),
+ NULL,
+ MINSIGSTKSZ
+};
+
+static Elf64_Brandinfo freebsd_brand_info = {
+ ELFOSABI_FREEBSD,
+ EM_SPARCV9,
+ "FreeBSD",
+ "",
+ "/usr/libexec/ld-elf.so.1",
+ &elf64_freebsd_sysvec
+ };
+
+SYSINIT(elf64, SI_SUB_EXEC, SI_ORDER_ANY,
+ (sysinit_cfunc_t) elf64_insert_brand_entry,
+ &freebsd_brand_info);
+
/*
* The following table holds for each relocation type:
* - the width in bits of the memory location the relocation
diff --git a/sys/sys/elf_generic.h b/sys/sys/elf_generic.h
index cf8da57832ed..cc0c471ad90c 100644
--- a/sys/sys/elf_generic.h
+++ b/sys/sys/elf_generic.h
@@ -50,6 +50,7 @@
#error "Unknown byte order"
#endif
+#define __elfN(x) __CONCAT(__CONCAT(__CONCAT(elf,__ELF_WORD_SIZE),_),x)
#define __ElfN(x) __CONCAT(__CONCAT(__CONCAT(Elf,__ELF_WORD_SIZE),_),x)
#define __ELFN(x) __CONCAT(__CONCAT(__CONCAT(ELF,__ELF_WORD_SIZE),_),x)
#define __ElfType(x) typedef __ElfN(x) __CONCAT(Elf_,x)
diff --git a/sys/sys/imgact.h b/sys/sys/imgact.h
index 6d599648b63b..819ae13547f7 100644
--- a/sys/sys/imgact.h
+++ b/sys/sys/imgact.h
@@ -67,7 +67,8 @@ struct image_params {
#ifdef _KERNEL
int exec_check_permissions(struct image_params *);
int exec_extract_strings(struct image_params *);
-int exec_new_vmspace(struct image_params *);
+int exec_new_vmspace(struct image_params *, vm_offset_t, vm_offset_t,
+ vm_offset_t);
int exec_shell_imgact(struct image_params *);
#endif
diff --git a/sys/sys/imgact_elf.h b/sys/sys/imgact_elf.h
index ecaf40d7dd69..1cc301487e18 100644
--- a/sys/sys/imgact_elf.h
+++ b/sys/sys/imgact_elf.h
@@ -37,6 +37,8 @@
#define AUXARGS_ENTRY(pos, id, val) {suword(pos++, id); suword(pos++, val);}
+struct thread;
+
#if ELF_TARG_CLASS == ELFCLASS32
/*
@@ -57,6 +59,7 @@ typedef struct {
typedef struct {
int brand;
+ int machine;
const char *compat_3_brand; /* pre Binutils 2.10 method (FBSD 3) */
const char *emul_path;
const char *interp_path;
@@ -65,9 +68,11 @@ typedef struct {
#define MAX_BRANDS 8
-int elf_brand_inuse(Elf32_Brandinfo *entry);
-int elf_insert_brand_entry(Elf32_Brandinfo *entry);
-int elf_remove_brand_entry(Elf32_Brandinfo *entry);
+int elf32_brand_inuse(Elf32_Brandinfo *entry);
+int elf32_insert_brand_entry(Elf32_Brandinfo *entry);
+int elf32_remove_brand_entry(Elf32_Brandinfo *entry);
+int elf32_freebsd_fixup(register_t **, struct image_params *);
+int elf32_coredump(struct thread *, struct vnode *, off_t);
#else /* !(ELF_TARG_CLASS == ELFCLASS32) */
@@ -89,6 +94,7 @@ typedef struct {
typedef struct {
int brand;
+ int machine;
const char *compat_3_brand; /* pre Binutils 2.10 method (FBSD 3) */
const char *emul_path;
const char *interp_path;
@@ -97,16 +103,14 @@ typedef struct {
#define MAX_BRANDS 8
-int elf_brand_inuse(Elf64_Brandinfo *entry);
-int elf_insert_brand_entry(Elf64_Brandinfo *entry);
-int elf_remove_brand_entry(Elf64_Brandinfo *entry);
+int elf64_brand_inuse(Elf64_Brandinfo *entry);
+int elf64_insert_brand_entry(Elf64_Brandinfo *entry);
+int elf64_remove_brand_entry(Elf64_Brandinfo *entry);
+int elf64_freebsd_fixup(register_t **, struct image_params *);
+int elf64_coredump(struct thread *, struct vnode *, off_t);
#endif /* ELF_TARG_CLASS == ELFCLASS32 */
-struct thread;
-
-int elf_coredump(struct thread *, struct vnode *, off_t);
-
#endif /* _KERNEL */
#endif /* !_SYS_IMGACT_ELF_H_ */
diff --git a/sys/sys/sysent.h b/sys/sys/sysent.h
index 19c9bc07b478..7271ccf947a1 100644
--- a/sys/sys/sysent.h
+++ b/sys/sys/sysent.h
@@ -79,6 +79,11 @@ struct sysentvec {
/* function to dump core, or NULL */
int (*sv_imgact_try)(struct image_params *);
int sv_minsigstksz; /* minimum signal stack size */
+ int sv_pagesize; /* pagesize override */
+ vm_offset_t sv_maxuser; /* VM_MAXUSER_ADDRESS override */
+ vm_offset_t sv_usrstack; /* USRSTACK override */
+ register_t *(*sv_copyout_strings)(struct image_params *);
+ void (*sv_setregs)(struct thread *, u_long, u_long, u_long);
};
#ifdef _KERNEL
diff --git a/sys/vm/vm_extern.h b/sys/vm/vm_extern.h
index d646f78a5d64..2a29faccd071 100644
--- a/sys/vm/vm_extern.h
+++ b/sys/vm/vm_extern.h
@@ -85,7 +85,7 @@ vm_offset_t vm_page_alloc_contig(vm_offset_t, vm_offset_t, vm_offset_t, vm_offse
void vm_set_page_size(void);
struct vmspace *vmspace_alloc(vm_offset_t, vm_offset_t);
struct vmspace *vmspace_fork(struct vmspace *);
-void vmspace_exec(struct proc *);
+void vmspace_exec(struct proc *, vm_offset_t, vm_offset_t);
void vmspace_unshare(struct proc *);
void vmspace_free(struct vmspace *);
void vmspace_exitfree(struct proc *);
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
index bbe5af6fa99f..ea1924ff83eb 100644
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -2586,14 +2586,13 @@ Retry:
* mapped to it, then create a new one. The new vmspace is null.
*/
void
-vmspace_exec(struct proc *p)
+vmspace_exec(struct proc *p, vm_offset_t minuser, vm_offset_t maxuser)
{
struct vmspace *oldvmspace = p->p_vmspace;
struct vmspace *newvmspace;
- vm_map_t map = &p->p_vmspace->vm_map;
GIANT_REQUIRED;
- newvmspace = vmspace_alloc(map->min_offset, map->max_offset);
+ newvmspace = vmspace_alloc(minuser, maxuser);
bcopy(&oldvmspace->vm_startcopy, &newvmspace->vm_startcopy,
(caddr_t) (newvmspace + 1) - (caddr_t) &newvmspace->vm_startcopy);
/*