summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authornwhitehorn <nwhitehorn@FreeBSD.org>2010-03-11 14:49:06 +0000
committernwhitehorn <nwhitehorn@FreeBSD.org>2010-03-11 14:49:06 +0000
commit142a4d29938aa4f7dde8d4ae621c479cc53fda36 (patch)
treee7bb2301107c48074cb0dbfffd43ee1f7e425d97 /sys/kern
parentd937b522a1d72eb6b270db5bf368d3fd1a79ebcf (diff)
downloadFreeBSD-src-142a4d29938aa4f7dde8d4ae621c479cc53fda36.zip
FreeBSD-src-142a4d29938aa4f7dde8d4ae621c479cc53fda36.tar.gz
Provide groundwork for 32-bit binary compatibility on non-x86 platforms,
for upcoming 64-bit PowerPC and MIPS support. This renames the COMPAT_IA32 option to COMPAT_FREEBSD32, removes some IA32-specific code from MI parts of the kernel and enhances the freebsd32 compatibility code to support big-endian platforms. Reviewed by: kib, jhb
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/imgact_elf.c15
-rw-r--r--sys/kern/kern_jail.c8
-rw-r--r--sys/kern/kern_module.c2
-rw-r--r--sys/kern/kern_thr.c2
-rw-r--r--sys/kern/kern_umtx.c6
-rw-r--r--sys/kern/sys_generic.c34
-rw-r--r--sys/kern/sys_process.c30
-rw-r--r--sys/kern/uipc_socket.c6
-rw-r--r--sys/kern/vfs_aio.c2
9 files changed, 65 insertions, 40 deletions
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index 7e48a3b..0fffb9f 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -75,11 +75,6 @@ __FBSDID("$FreeBSD$");
#include <machine/elf.h>
#include <machine/md_var.h>
-#if defined(COMPAT_IA32) && __ELF_WORD_SIZE == 32
-#include <machine/fpu.h>
-#include <compat/ia32/ia32_reg.h>
-#endif
-
#define OLD_EI_BRAND 8
static int __elfN(check_header)(const Elf_Ehdr *hdr);
@@ -1303,7 +1298,9 @@ __elfN(corehdr)(td, vp, cred, numsegs, hdr, hdrsize, gzfile)
}
}
-#if defined(COMPAT_IA32) && __ELF_WORD_SIZE == 32
+#if defined(COMPAT_FREEBSD32) && __ELF_WORD_SIZE == 32
+#include <compat/freebsd32/freebsd32.h>
+
typedef struct prstatus32 elf_prstatus_t;
typedef struct prpsinfo32 elf_prpsinfo_t;
typedef struct fpreg32 elf_prfpregset_t;
@@ -1387,7 +1384,7 @@ __elfN(puthdr)(struct thread *td, void *dst, size_t *off, int numsegs)
status->pr_osreldate = osreldate;
status->pr_cursig = p->p_sig;
status->pr_pid = thr->td_tid;
-#if defined(COMPAT_IA32) && __ELF_WORD_SIZE == 32
+#if defined(COMPAT_FREEBSD32) && __ELF_WORD_SIZE == 32
fill_regs32(thr, &status->pr_reg);
fill_fpregs32(thr, fpregset);
#else
@@ -1439,8 +1436,8 @@ __elfN(puthdr)(struct thread *td, void *dst, size_t *off, int numsegs)
ehdr->e_ident[EI_ABIVERSION] = 0;
ehdr->e_ident[EI_PAD] = 0;
ehdr->e_type = ET_CORE;
-#if defined(COMPAT_IA32) && __ELF_WORD_SIZE == 32
- ehdr->e_machine = EM_386;
+#if defined(COMPAT_FREEBSD32) && __ELF_WORD_SIZE == 32
+ ehdr->e_machine = ELF_ARCH32;
#else
ehdr->e_machine = ELF_ARCH;
#endif
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
index 93fdfa9..d419833 100644
--- a/sys/kern/kern_jail.c
+++ b/sys/kern/kern_jail.c
@@ -734,8 +734,8 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
}
}
-#ifdef COMPAT_IA32
- if (td->td_proc->p_sysent->sv_flags & SV_IA32) {
+#ifdef COMPAT_FREEBSD32
+ if (td->td_proc->p_sysent->sv_flags & SV_ILP32) {
uint32_t hid32;
error = vfs_copyopt(opts, "host.hostid", &hid32, sizeof(hid32));
@@ -1961,8 +1961,8 @@ kern_jail_get(struct thread *td, struct uio *optuio, int flags)
error = vfs_setopts(opts, "host.hostuuid", pr->pr_hostuuid);
if (error != 0 && error != ENOENT)
goto done_deref;
-#ifdef COMPAT_IA32
- if (td->td_proc->p_sysent->sv_flags & SV_IA32) {
+#ifdef COMPAT_FREEBSD32
+ if (td->td_proc->p_sysent->sv_flags & SV_ILP32) {
uint32_t hid32 = pr->pr_hostid;
error = vfs_setopt(opts, "host.hostid", &hid32, sizeof(hid32));
diff --git a/sys/kern/kern_module.c b/sys/kern/kern_module.c
index 9c53bf6..0409344 100644
--- a/sys/kern/kern_module.c
+++ b/sys/kern/kern_module.c
@@ -446,7 +446,7 @@ modfind(struct thread *td, struct modfind_args *uap)
MODULE_VERSION(kernel, __FreeBSD_version);
-#ifdef COMPAT_IA32
+#ifdef COMPAT_FREEBSD32
#include <sys/mount.h>
#include <sys/socket.h>
#include <compat/freebsd32/freebsd32_util.h>
diff --git a/sys/kern/kern_thr.c b/sys/kern/kern_thr.c
index 116e79b..0b90dfc 100644
--- a/sys/kern/kern_thr.c
+++ b/sys/kern/kern_thr.c
@@ -55,7 +55,7 @@ __FBSDID("$FreeBSD$");
#include <security/audit/audit.h>
-#ifdef COMPAT_IA32
+#ifdef COMPAT_FREEBSD32
static inline int
suword_lwpid(void *addr, lwpid_t lwpid)
diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c
index 14a79a3..137ffe5 100644
--- a/sys/kern/kern_umtx.c
+++ b/sys/kern/kern_umtx.c
@@ -54,7 +54,7 @@ __FBSDID("$FreeBSD$");
#include <machine/cpu.h>
-#ifdef COMPAT_IA32
+#ifdef COMPAT_FREEBSD32
#include <compat/freebsd32/freebsd32_proto.h>
#endif
@@ -818,7 +818,7 @@ do_unlock_umtx(struct thread *td, struct umtx *umtx, u_long id)
return (0);
}
-#ifdef COMPAT_IA32
+#ifdef COMPAT_FREEBSD32
/*
* Lock a umtx object.
@@ -3269,7 +3269,7 @@ _umtx_op(struct thread *td, struct _umtx_op_args *uap)
return (EINVAL);
}
-#ifdef COMPAT_IA32
+#ifdef COMPAT_FREEBSD32
int
freebsd32_umtx_lock(struct thread *td, struct freebsd32_umtx_lock_args *uap)
/* struct umtx *umtx */
diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c
index b34af61..eaefd9c 100644
--- a/sys/kern/sys_generic.c
+++ b/sys/kern/sys_generic.c
@@ -878,9 +878,10 @@ kern_select(struct thread *td, int nd, fd_set *fd_in, fd_set *fd_ou,
sbp = selbits;
#define getbits(name, x) \
do { \
- if (name == NULL) \
+ if (name == NULL) { \
ibits[x] = NULL; \
- else { \
+ obits[x] = NULL; \
+ } else { \
ibits[x] = sbp + nbufbytes / 2 / sizeof *sbp; \
obits[x] = sbp; \
sbp += ncpbytes / sizeof *sbp; \
@@ -895,6 +896,28 @@ kern_select(struct thread *td, int nd, fd_set *fd_in, fd_set *fd_ou,
getbits(fd_ou, 1);
getbits(fd_ex, 2);
#undef getbits
+
+#if BYTE_ORDER == BIG_ENDIAN && defined(__LP64__)
+ /*
+ * XXX: swizzle_fdset assumes that if abi_nfdbits != NFDBITS,
+ * we are running under 32-bit emulation. This should be more
+ * generic.
+ */
+#define swizzle_fdset(bits) \
+ if (abi_nfdbits != NFDBITS && bits != NULL) { \
+ int i; \
+ for (i = 0; i < ncpbytes / sizeof *sbp; i++) \
+ bits[i] = (bits[i] >> 32) | (bits[i] << 32); \
+ }
+#else
+#define swizzle_fdset(bits)
+#endif
+
+ /* Make sure the bit order makes it through an ABI transition */
+ swizzle_fdset(ibits[0]);
+ swizzle_fdset(ibits[1]);
+ swizzle_fdset(ibits[2]);
+
if (nbufbytes != 0)
bzero(selbits, nbufbytes / 2);
@@ -941,6 +964,13 @@ done:
error = EINTR;
if (error == EWOULDBLOCK)
error = 0;
+
+ /* swizzle bit order back, if necessary */
+ swizzle_fdset(obits[0]);
+ swizzle_fdset(obits[1]);
+ swizzle_fdset(obits[2]);
+#undef swizzle_fdset
+
#define putbits(name, x) \
if (name && (error2 = copyout(obits[x], name, ncpubytes))) \
error = error2;
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
index d4b5d4d..f5671d9 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -62,10 +62,8 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_pager.h>
#include <vm/vm_param.h>
-#ifdef COMPAT_IA32
+#ifdef COMPAT_FREEBSD32
#include <sys/procfs.h>
-#include <machine/fpu.h>
-#include <compat/ia32/ia32_reg.h>
struct ptrace_io_desc32 {
int piod_op;
@@ -172,7 +170,7 @@ proc_write_fpregs(struct thread *td, struct fpreg *fpregs)
PROC_ACTION(set_fpregs(td, fpregs));
}
-#ifdef COMPAT_IA32
+#ifdef COMPAT_FREEBSD32
/* For 32 bit binaries, we need to expose the 32 bit regs layouts. */
int
proc_read_regs32(struct thread *td, struct reg32 *regs32)
@@ -473,7 +471,7 @@ ptrace_vm_entry(struct thread *td, struct proc *p, struct ptrace_vm_entry *pve)
return (error);
}
-#ifdef COMPAT_IA32
+#ifdef COMPAT_FREEBSD32
static int
ptrace_vm_entry32(struct thread *td, struct proc *p,
struct ptrace_vm_entry32 *pve32)
@@ -500,7 +498,7 @@ ptrace_vm_entry32(struct thread *td, struct proc *p,
pve32->pve_pathlen = pve.pve_pathlen;
return (error);
}
-#endif /* COMPAT_IA32 */
+#endif /* COMPAT_FREEBSD32 */
/*
* Process debugging system call.
@@ -514,7 +512,7 @@ struct ptrace_args {
};
#endif
-#ifdef COMPAT_IA32
+#ifdef COMPAT_FREEBSD32
/*
* This CPP subterfuge is to try and reduce the number of ifdefs in
* the body of the code.
@@ -549,7 +547,7 @@ ptrace(struct thread *td, struct ptrace_args *uap)
struct dbreg dbreg;
struct fpreg fpreg;
struct reg reg;
-#ifdef COMPAT_IA32
+#ifdef COMPAT_FREEBSD32
struct dbreg32 dbreg32;
struct fpreg32 fpreg32;
struct reg32 reg32;
@@ -559,7 +557,7 @@ ptrace(struct thread *td, struct ptrace_args *uap)
} r;
void *addr;
int error = 0;
-#ifdef COMPAT_IA32
+#ifdef COMPAT_FREEBSD32
int wrap32 = 0;
if (SV_CURPROC_FLAG(SV_ILP32))
@@ -627,7 +625,7 @@ ptrace(struct thread *td, struct ptrace_args *uap)
#undef COPYIN
#undef COPYOUT
-#ifdef COMPAT_IA32
+#ifdef COMPAT_FREEBSD32
/*
* PROC_READ(regs, td2, addr);
* becomes either:
@@ -661,7 +659,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
int error, write, tmp, num;
int proctree_locked = 0;
lwpid_t tid = 0, *buf;
-#ifdef COMPAT_IA32
+#ifdef COMPAT_FREEBSD32
int wrap32 = 0, safe = 0;
struct ptrace_io_desc32 *piod32 = NULL;
#endif
@@ -749,7 +747,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
tid = td2->td_tid;
}
-#ifdef COMPAT_IA32
+#ifdef COMPAT_FREEBSD32
/*
* Test if we're a 32 bit client and what the target is.
* Set the wrap controls accordingly.
@@ -1017,7 +1015,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
break;
case PT_IO:
-#ifdef COMPAT_IA32
+#ifdef COMPAT_FREEBSD32
if (wrap32) {
piod32 = addr;
iov.iov_base = (void *)(uintptr_t)piod32->piod_addr;
@@ -1037,7 +1035,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
uio.uio_iovcnt = 1;
uio.uio_segflg = UIO_USERSPACE;
uio.uio_td = td;
-#ifdef COMPAT_IA32
+#ifdef COMPAT_FREEBSD32
tmp = wrap32 ? piod32->piod_op : piod->piod_op;
#else
tmp = piod->piod_op;
@@ -1058,7 +1056,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
}
PROC_UNLOCK(p);
error = proc_rwmem(p, &uio);
-#ifdef COMPAT_IA32
+#ifdef COMPAT_FREEBSD32
if (wrap32)
piod32->piod_len -= uio.uio_resid;
else
@@ -1147,7 +1145,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
case PT_VM_ENTRY:
PROC_UNLOCK(p);
-#ifdef COMPAT_IA32
+#ifdef COMPAT_FREEBSD32
if (wrap32)
error = ptrace_vm_entry32(td, p, addr);
else
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index 5cbdc40..569aed0 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -136,7 +136,7 @@ __FBSDID("$FreeBSD$");
#include <vm/uma.h>
-#ifdef COMPAT_IA32
+#ifdef COMPAT_FREEBSD32
#include <sys/mount.h>
#include <sys/sysent.h>
#include <compat/freebsd32/freebsd32.h>
@@ -2507,7 +2507,7 @@ sosetopt(struct socket *so, struct sockopt *sopt)
case SO_SNDTIMEO:
case SO_RCVTIMEO:
-#ifdef COMPAT_IA32
+#ifdef COMPAT_FREEBSD32
if (SV_CURPROC_FLAG(SV_ILP32)) {
struct timeval32 tv32;
@@ -2688,7 +2688,7 @@ integer:
tv.tv_sec = optval / hz;
tv.tv_usec = (optval % hz) * tick;
-#ifdef COMPAT_IA32
+#ifdef COMPAT_FREEBSD32
if (SV_CURPROC_FLAG(SV_ILP32)) {
struct timeval32 tv32;
diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c
index 088e4f6..25328d6 100644
--- a/sys/kern/vfs_aio.c
+++ b/sys/kern/vfs_aio.c
@@ -2532,7 +2532,7 @@ filt_lio(struct knote *kn, long hint)
return (lj->lioj_flags & LIOJ_KEVENT_POSTED);
}
-#ifdef COMPAT_IA32
+#ifdef COMPAT_FREEBSD32
#include <sys/mount.h>
#include <sys/socket.h>
#include <compat/freebsd32/freebsd32.h>
OpenPOWER on IntegriCloud