From 142a4d29938aa4f7dde8d4ae621c479cc53fda36 Mon Sep 17 00:00:00 2001 From: nwhitehorn Date: Thu, 11 Mar 2010 14:49:06 +0000 Subject: 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 --- sys/kern/imgact_elf.c | 15 ++++++--------- sys/kern/kern_jail.c | 8 ++++---- sys/kern/kern_module.c | 2 +- sys/kern/kern_thr.c | 2 +- sys/kern/kern_umtx.c | 6 +++--- sys/kern/sys_generic.c | 34 ++++++++++++++++++++++++++++++++-- sys/kern/sys_process.c | 30 ++++++++++++++---------------- sys/kern/uipc_socket.c | 6 +++--- sys/kern/vfs_aio.c | 2 +- 9 files changed, 65 insertions(+), 40 deletions(-) (limited to 'sys/kern') 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 #include -#if defined(COMPAT_IA32) && __ELF_WORD_SIZE == 32 -#include -#include -#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 + 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 #include #include 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 -#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 -#ifdef COMPAT_IA32 +#ifdef COMPAT_FREEBSD32 #include #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 #include -#ifdef COMPAT_IA32 +#ifdef COMPAT_FREEBSD32 #include -#include -#include 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 -#ifdef COMPAT_IA32 +#ifdef COMPAT_FREEBSD32 #include #include #include @@ -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 #include #include -- cgit v1.1