svn commit: r220238 - in head/sys: amd64/ia32 compat/freebsd32
compat/ia32 ia64/ia32 kern modules sys
Alexander Best
arundel at freebsd.org
Fri Apr 1 11:45:00 UTC 2011
On Fri Apr 1 11, Konstantin Belousov wrote:
> Author: kib
> Date: Fri Apr 1 11:16:29 2011
> New Revision: 220238
> URL: http://svn.freebsd.org/changeset/base/220238
>
> Log:
> Add support for executing the FreeBSD 1/i386 a.out binaries on amd64.
>
> In particular:
> - implement compat shims for old stat(2) variants and ogetdirentries(2);
> - implement delivery of signals with ancient stack frame layout and
> corresponding sigreturn(2);
> - implement old getpagesize(2);
> - provide a user-mode trampoline and LDT call gate for lcall $7,$0;
> - port a.out image activator and connect it to the build as a module
> on amd64.
>
> The changes are hidden under COMPAT_43.
hmm...for i386 there's
# Enable i386 a.out binary support
options COMPAT_AOUT
why not make this feature dependant upon the same option and not COMPAT_43?
...also i noticed sys/amd/conf/NOTES says:
# Enable 32-bit Linux ABI emulation (requires COMPAT_43 and COMPAT_FREEBSD32)
options COMPAT_LINUX32
...i don't think COMPAT_43 is actually necessary to use COMPAT_FREEBSD32, is
it?
cheers.
alex
>
> MFC after: 1 month
>
> Modified:
> head/sys/amd64/ia32/ia32_misc.c
> head/sys/amd64/ia32/ia32_signal.c
> head/sys/amd64/ia32/ia32_sigtramp.S
> head/sys/amd64/ia32/ia32_syscall.c
> head/sys/compat/freebsd32/freebsd32_misc.c
> head/sys/compat/freebsd32/syscalls.master
> head/sys/compat/ia32/ia32_genassym.c
> head/sys/compat/ia32/ia32_signal.h
> head/sys/compat/ia32/ia32_sysvec.c
> head/sys/compat/ia32/ia32_util.h
> head/sys/ia64/ia32/ia32_misc.c
> head/sys/ia64/ia32/ia32_signal.c
> head/sys/kern/imgact_aout.c
> head/sys/kern/vfs_syscalls.c
> head/sys/modules/Makefile
> head/sys/sys/syscallsubr.h
>
> Modified: head/sys/amd64/ia32/ia32_misc.c
> ==============================================================================
> --- head/sys/amd64/ia32/ia32_misc.c Fri Apr 1 06:28:21 2011 (r220237)
> +++ head/sys/amd64/ia32/ia32_misc.c Fri Apr 1 11:16:29 2011 (r220238)
> @@ -69,3 +69,14 @@ freebsd32_sysarch(struct thread *td, str
> return (sysarch(td, &uap1));
> }
> }
> +
> +#ifdef COMPAT_43
> +int
> +ofreebsd32_getpagesize(struct thread *td,
> + struct ofreebsd32_getpagesize_args *uap)
> +{
> +
> + td->td_retval[0] = IA32_PAGE_SIZE;
> + return (0);
> +}
> +#endif
>
> Modified: head/sys/amd64/ia32/ia32_signal.c
> ==============================================================================
> --- head/sys/amd64/ia32/ia32_signal.c Fri Apr 1 06:28:21 2011 (r220237)
> +++ head/sys/amd64/ia32/ia32_signal.c Fri Apr 1 11:16:29 2011 (r220238)
> @@ -300,6 +300,109 @@ freebsd32_swapcontext(struct thread *td,
> * frame pointer, it returns to the user
> * specified pc, psl.
> */
> +
> +#ifdef COMPAT_43
> +static void
> +ia32_osendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
> +{
> + struct ia32_sigframe3 sf, *fp;
> + struct proc *p;
> + struct thread *td;
> + struct sigacts *psp;
> + struct trapframe *regs;
> + int sig;
> + int oonstack;
> +
> + td = curthread;
> + p = td->td_proc;
> + PROC_LOCK_ASSERT(p, MA_OWNED);
> + sig = ksi->ksi_signo;
> + psp = p->p_sigacts;
> + mtx_assert(&psp->ps_mtx, MA_OWNED);
> + regs = td->td_frame;
> + oonstack = sigonstack(regs->tf_rsp);
> +
> + /* Allocate space for the signal handler context. */
> + if ((td->td_pflags & TDP_ALTSTACK) && !oonstack &&
> + SIGISMEMBER(psp->ps_sigonstack, sig)) {
> + fp = (struct ia32_sigframe3 *)(td->td_sigstk.ss_sp +
> + td->td_sigstk.ss_size - sizeof(sf));
> + td->td_sigstk.ss_flags |= SS_ONSTACK;
> + } else
> + fp = (struct ia32_sigframe3 *)regs->tf_rsp - 1;
> +
> + /* Translate the signal if appropriate. */
> + if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
> + sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
> +
> + /* Build the argument list for the signal handler. */
> + sf.sf_signum = sig;
> + sf.sf_scp = (register_t)&fp->sf_siginfo.si_sc;
> + if (SIGISMEMBER(psp->ps_siginfo, sig)) {
> + /* Signal handler installed with SA_SIGINFO. */
> + sf.sf_arg2 = (register_t)&fp->sf_siginfo;
> + sf.sf_siginfo.si_signo = sig;
> + sf.sf_siginfo.si_code = ksi->ksi_code;
> + sf.sf_ah = (uintptr_t)catcher;
> + } else {
> + /* Old FreeBSD-style arguments. */
> + sf.sf_arg2 = ksi->ksi_code;
> + sf.sf_addr = (register_t)ksi->ksi_addr;
> + sf.sf_ah = (uintptr_t)catcher;
> + }
> + mtx_unlock(&psp->ps_mtx);
> + PROC_UNLOCK(p);
> +
> + /* Save most if not all of trap frame. */
> + sf.sf_siginfo.si_sc.sc_eax = regs->tf_rax;
> + sf.sf_siginfo.si_sc.sc_ebx = regs->tf_rbx;
> + sf.sf_siginfo.si_sc.sc_ecx = regs->tf_rcx;
> + sf.sf_siginfo.si_sc.sc_edx = regs->tf_rdx;
> + sf.sf_siginfo.si_sc.sc_esi = regs->tf_rsi;
> + sf.sf_siginfo.si_sc.sc_edi = regs->tf_rdi;
> + sf.sf_siginfo.si_sc.sc_cs = regs->tf_cs;
> + sf.sf_siginfo.si_sc.sc_ds = regs->tf_ds;
> + sf.sf_siginfo.si_sc.sc_ss = regs->tf_ss;
> + sf.sf_siginfo.si_sc.sc_es = regs->tf_es;
> + sf.sf_siginfo.si_sc.sc_fs = regs->tf_fs;
> + sf.sf_siginfo.si_sc.sc_gs = regs->tf_gs;
> + sf.sf_siginfo.si_sc.sc_isp = regs->tf_rsp;
> +
> + /* Build the signal context to be used by osigreturn(). */
> + sf.sf_siginfo.si_sc.sc_onstack = (oonstack) ? 1 : 0;
> + SIG2OSIG(*mask, sf.sf_siginfo.si_sc.sc_mask);
> + sf.sf_siginfo.si_sc.sc_esp = regs->tf_rsp;
> + sf.sf_siginfo.si_sc.sc_ebp = regs->tf_rbp;
> + sf.sf_siginfo.si_sc.sc_eip = regs->tf_rip;
> + sf.sf_siginfo.si_sc.sc_eflags = regs->tf_rflags;
> + sf.sf_siginfo.si_sc.sc_trapno = regs->tf_trapno;
> + sf.sf_siginfo.si_sc.sc_err = regs->tf_err;
> +
> + /*
> + * Copy the sigframe out to the user's stack.
> + */
> + if (copyout(&sf, fp, sizeof(*fp)) != 0) {
> +#ifdef DEBUG
> + printf("process %ld has trashed its stack\n", (long)p->p_pid);
> +#endif
> + PROC_LOCK(p);
> + sigexit(td, SIGILL);
> + }
> +
> + regs->tf_rsp = (uintptr_t)fp;
> + regs->tf_rip = p->p_sysent->sv_psstrings - sz_ia32_osigcode;
> + regs->tf_rflags &= ~(PSL_T | PSL_D);
> + regs->tf_cs = _ucode32sel;
> + regs->tf_ds = _udatasel;
> + regs->tf_es = _udatasel;
> + regs->tf_fs = _udatasel;
> + regs->tf_ss = _udatasel;
> + set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
> + PROC_LOCK(p);
> + mtx_lock(&psp->ps_mtx);
> +}
> +#endif
> +
> #ifdef COMPAT_FREEBSD4
> static void
> freebsd4_ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
> @@ -441,6 +544,12 @@ ia32_sendsig(sig_t catcher, ksiginfo_t *
> return;
> }
> #endif
> +#ifdef COMPAT_43
> + if (SIGISMEMBER(psp->ps_osigset, sig)) {
> + ia32_osendsig(catcher, ksi, mask);
> + return;
> + }
> +#endif
> mtx_assert(&psp->ps_mtx, MA_OWNED);
> regs = td->td_frame;
> oonstack = sigonstack(regs->tf_rsp);
> @@ -547,6 +656,64 @@ ia32_sendsig(sig_t catcher, ksiginfo_t *
> * make sure that the user has not modified the
> * state to gain improper privileges.
> */
> +
> +#ifdef COMPAT_43
> +int
> +ofreebsd32_sigreturn(struct thread *td, struct ofreebsd32_sigreturn_args *uap)
> +{
> + struct ia32_sigcontext3 sc, *scp;
> + struct trapframe *regs;
> + int eflags, error;
> + ksiginfo_t ksi;
> +
> + regs = td->td_frame;
> + error = copyin(uap->sigcntxp, &sc, sizeof(sc));
> + if (error != 0)
> + return (error);
> + scp = ≻
> + eflags = scp->sc_eflags;
> + if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) {
> + return (EINVAL);
> + }
> + if (!CS_SECURE(scp->sc_cs)) {
> + ksiginfo_init_trap(&ksi);
> + ksi.ksi_signo = SIGBUS;
> + ksi.ksi_code = BUS_OBJERR;
> + ksi.ksi_trapno = T_PROTFLT;
> + ksi.ksi_addr = (void *)regs->tf_rip;
> + trapsignal(td, &ksi);
> + return (EINVAL);
> + }
> + regs->tf_ds = scp->sc_ds;
> + regs->tf_es = scp->sc_es;
> + regs->tf_fs = scp->sc_fs;
> + regs->tf_gs = scp->sc_gs;
> +
> + regs->tf_rax = scp->sc_eax;
> + regs->tf_rbx = scp->sc_ebx;
> + regs->tf_rcx = scp->sc_ecx;
> + regs->tf_rdx = scp->sc_edx;
> + regs->tf_rsi = scp->sc_esi;
> + regs->tf_rdi = scp->sc_edi;
> + regs->tf_cs = scp->sc_cs;
> + regs->tf_ss = scp->sc_ss;
> + regs->tf_rbp = scp->sc_ebp;
> + regs->tf_rsp = scp->sc_esp;
> + regs->tf_rip = scp->sc_eip;
> + regs->tf_rflags = eflags;
> +
> + if (scp->sc_onstack & 1)
> + td->td_sigstk.ss_flags |= SS_ONSTACK;
> + else
> + td->td_sigstk.ss_flags &= ~SS_ONSTACK;
> +
> + kern_sigprocmask(td, SIG_SETMASK, (sigset_t *)&scp->sc_mask, NULL,
> + SIGPROCMASK_OLD);
> + set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
> + return (EJUSTRETURN);
> +}
> +#endif
> +
> #ifdef COMPAT_FREEBSD4
> /*
> * MPSAFE
> @@ -734,6 +901,9 @@ ia32_setregs(struct thread *td, struct i
> user_ldt_free(td);
> else
> mtx_unlock(&dt_lock);
> +#ifdef COMPAT_43
> + setup_lcall_gate();
> +#endif
>
> pcb->pcb_fsbase = 0;
> pcb->pcb_gsbase = 0;
>
> Modified: head/sys/amd64/ia32/ia32_sigtramp.S
> ==============================================================================
> --- head/sys/amd64/ia32/ia32_sigtramp.S Fri Apr 1 06:28:21 2011 (r220237)
> +++ head/sys/amd64/ia32/ia32_sigtramp.S Fri Apr 1 11:16:29 2011 (r220238)
> @@ -66,6 +66,35 @@ freebsd4_ia32_sigcode:
> jmp 1b
> #endif
>
> +#ifdef COMPAT_43
> + ALIGN_TEXT
> +ia32_osigcode:
> + calll *IA32_SIGF_HANDLER(%esp)/* call signal handler */
> + leal IA32_SIGF_SC(%esp),%eax /* get sigcontext */
> + pushl %eax
> + movl $103,%eax /* 3.x SYS_sigreturn */
> + pushl %eax /* junk to fake return addr. */
> + int $0x80 /* enter kernel with args */
> +1:
> + jmp 1b
> +
> +
> + ALIGN_TEXT
> +lcall_tramp:
> + pushl %ebp
> + movl %esp,%ebp
> + pushl 0x24(%ebp) /* arg 6 */
> + pushl 0x20(%ebp)
> + pushl 0x1c(%ebp)
> + pushl 0x18(%ebp)
> + pushl 0x14(%ebp)
> + pushl 0x10(%ebp) /* arg 1 */
> + pushl 0xc(%ebp) /* gap */
> + int $0x80
> + leave
> + lretl
> +#endif
> +
> ALIGN_TEXT
> esigcode:
>
> @@ -78,3 +107,11 @@ sz_ia32_sigcode:
> sz_freebsd4_ia32_sigcode:
> .long esigcode-freebsd4_ia32_sigcode
> #endif
> +#ifdef COMPAT_43
> + .globl sz_ia32_osigcode
> +sz_ia32_osigcode:
> + .long esigcode-ia32_osigcode
> + .globl sz_lcall_tramp
> +sz_lcall_tramp:
> + .long esigcode-lcall_tramp
> +#endif
>
> Modified: head/sys/amd64/ia32/ia32_syscall.c
> ==============================================================================
> --- head/sys/amd64/ia32/ia32_syscall.c Fri Apr 1 06:28:21 2011 (r220237)
> +++ head/sys/amd64/ia32/ia32_syscall.c Fri Apr 1 11:16:29 2011 (r220238)
> @@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
> */
>
> #include "opt_clock.h"
> +#include "opt_compat.h"
> #include "opt_cpu.h"
> #include "opt_isa.h"
>
> @@ -78,7 +79,17 @@ __FBSDID("$FreeBSD$");
> #include <machine/intr_machdep.h>
> #include <machine/md_var.h>
>
> +#include <compat/freebsd32/freebsd32_signal.h>
> #include <compat/freebsd32/freebsd32_util.h>
> +#include <compat/ia32/ia32_signal.h>
> +#include <machine/psl.h>
> +#include <machine/segments.h>
> +#include <machine/specialreg.h>
> +#include <machine/sysarch.h>
> +#include <machine/frame.h>
> +#include <machine/md_var.h>
> +#include <machine/pcb.h>
> +#include <machine/cpufunc.h>
>
> #define IDTVEC(name) __CONCAT(X,name)
>
> @@ -198,3 +209,45 @@ ia32_syscall_disable(void *dummy)
>
> SYSINIT(ia32_syscall, SI_SUB_EXEC, SI_ORDER_ANY, ia32_syscall_enable, NULL);
> SYSUNINIT(ia32_syscall, SI_SUB_EXEC, SI_ORDER_ANY, ia32_syscall_disable, NULL);
> +
> +#ifdef COMPAT_43
> +int
> +setup_lcall_gate(void)
> +{
> + struct i386_ldt_args uap;
> + struct user_segment_descriptor descs[2];
> + struct gate_descriptor *ssd;
> + uint32_t lcall_addr;
> + int error;
> +
> + bzero(&uap, sizeof(uap));
> + uap.start = 0;
> + uap.num = 2;
> +
> + /*
> + * This is the easiest way to cut the space for system
> + * descriptor in ldt. Manually adjust the descriptor type to
> + * the call gate later.
> + */
> + bzero(&descs[0], sizeof(descs));
> + descs[0].sd_type = SDT_SYSNULL;
> + descs[1].sd_type = SDT_SYSNULL;
> + error = amd64_set_ldt(curthread, &uap, descs);
> + if (error != 0)
> + return (error);
> +
> + lcall_addr = curproc->p_sysent->sv_psstrings - sz_lcall_tramp;
> + mtx_lock(&dt_lock);
> + ssd = (struct gate_descriptor *)(curproc->p_md.md_ldt->ldt_base);
> + bzero(ssd, sizeof(*ssd));
> + ssd->gd_looffset = lcall_addr;
> + ssd->gd_hioffset = lcall_addr >> 16;
> + ssd->gd_selector = _ucode32sel;
> + ssd->gd_type = SDT_SYSCGT;
> + ssd->gd_dpl = SEL_UPL;
> + ssd->gd_p = 1;
> + mtx_unlock(&dt_lock);
> +
> + return (0);
> +}
> +#endif
>
> Modified: head/sys/compat/freebsd32/freebsd32_misc.c
> ==============================================================================
> --- head/sys/compat/freebsd32/freebsd32_misc.c Fri Apr 1 06:28:21 2011 (r220237)
> +++ head/sys/compat/freebsd32/freebsd32_misc.c Fri Apr 1 11:16:29 2011 (r220238)
> @@ -1454,6 +1454,29 @@ freebsd32_ftruncate(struct thread *td, s
> return (ftruncate(td, &ap));
> }
>
> +#ifdef COMPAT_43
> +int
> +ofreebsd32_getdirentries(struct thread *td,
> + struct ofreebsd32_getdirentries_args *uap)
> +{
> + struct ogetdirentries_args ap;
> + int error;
> + long loff;
> + int32_t loff_cut;
> +
> + ap.fd = uap->fd;
> + ap.buf = uap->buf;
> + ap.count = uap->count;
> + ap.basep = NULL;
> + error = kern_ogetdirentries(td, &ap, &loff);
> + if (error == 0) {
> + loff_cut = loff;
> + error = copyout(&loff_cut, uap->basep, sizeof(int32_t));
> + }
> + return (error);
> +}
> +#endif
> +
> int
> freebsd32_getdirentries(struct thread *td,
> struct freebsd32_getdirentries_args *uap)
> @@ -1638,6 +1661,29 @@ copy_stat(struct stat *in, struct stat32
> TS_CP(*in, *out, st_birthtim);
> }
>
> +#ifdef COMPAT_43
> +static void
> +copy_ostat(struct stat *in, struct ostat32 *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);
> + CP(*in, *out, st_size);
> + TS_CP(*in, *out, st_atim);
> + TS_CP(*in, *out, st_mtim);
> + TS_CP(*in, *out, st_ctim);
> + CP(*in, *out, st_blksize);
> + CP(*in, *out, st_blocks);
> + CP(*in, *out, st_flags);
> + CP(*in, *out, st_gen);
> +}
> +#endif
> +
> int
> freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
> {
> @@ -1653,6 +1699,23 @@ freebsd32_stat(struct thread *td, struct
> return (error);
> }
>
> +#ifdef COMPAT_43
> +int
> +ofreebsd32_stat(struct thread *td, struct ofreebsd32_stat_args *uap)
> +{
> + struct stat sb;
> + struct ostat32 sb32;
> + int error;
> +
> + error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
> + if (error)
> + return (error);
> + copy_ostat(&sb, &sb32);
> + error = copyout(&sb32, uap->ub, sizeof (sb32));
> + return (error);
> +}
> +#endif
> +
> int
> freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
> {
> @@ -1668,6 +1731,23 @@ freebsd32_fstat(struct thread *td, struc
> return (error);
> }
>
> +#ifdef COMPAT_43
> +int
> +ofreebsd32_fstat(struct thread *td, struct ofreebsd32_fstat_args *uap)
> +{
> + struct stat ub;
> + struct ostat32 ub32;
> + int error;
> +
> + error = kern_fstat(td, uap->fd, &ub);
> + if (error)
> + return (error);
> + copy_ostat(&ub, &ub32);
> + error = copyout(&ub32, uap->ub, sizeof(ub32));
> + return (error);
> +}
> +#endif
> +
> int
> freebsd32_fstatat(struct thread *td, struct freebsd32_fstatat_args *uap)
> {
> @@ -1698,9 +1778,23 @@ freebsd32_lstat(struct thread *td, struc
> return (error);
> }
>
> -/*
> - * MPSAFE
> - */
> +#ifdef COMPAT_43
> +int
> +ofreebsd32_lstat(struct thread *td, struct ofreebsd32_lstat_args *uap)
> +{
> + struct stat sb;
> + struct ostat32 sb32;
> + int error;
> +
> + error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
> + if (error)
> + return (error);
> + copy_ostat(&sb, &sb32);
> + error = copyout(&sb32, uap->ub, sizeof (sb32));
> + return (error);
> +}
> +#endif
> +
> int
> freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
> {
>
> Modified: head/sys/compat/freebsd32/syscalls.master
> ==============================================================================
> --- head/sys/compat/freebsd32/syscalls.master Fri Apr 1 06:28:21 2011 (r220237)
> +++ head/sys/compat/freebsd32/syscalls.master Fri Apr 1 11:16:29 2011 (r220238)
> @@ -117,9 +117,11 @@
> 35 AUE_FCHFLAGS NOPROTO { int fchflags(int fd, int flags); }
> 36 AUE_SYNC NOPROTO { int sync(void); }
> 37 AUE_KILL NOPROTO { int kill(int pid, int signum); }
> -38 AUE_STAT UNIMPL ostat
> +38 AUE_STAT COMPAT { int freebsd32_stat(char *path, \
> + struct ostat32 *ub); }
> 39 AUE_GETPPID NOPROTO { pid_t getppid(void); }
> -40 AUE_LSTAT UNIMPL olstat
> +40 AUE_LSTAT COMPAT { int freebsd32_lstat(char *path, \
> + struct ostat *ub); }
> 41 AUE_DUP NOPROTO { int dup(u_int fd); }
> 42 AUE_PIPE NOPROTO { int pipe(void); }
> 43 AUE_GETEGID NOPROTO { gid_t getegid(void); }
> @@ -153,9 +155,11 @@
> 60 AUE_UMASK NOPROTO { int umask(int newmask); } umask \
> umask_args int
> 61 AUE_CHROOT NOPROTO { int chroot(char *path); }
> -62 AUE_FSTAT OBSOL ofstat
> +62 AUE_FSTAT COMPAT { int freebsd32_fstat(int fd, \
> + struct ostat32 *ub); }
> 63 AUE_NULL OBSOL ogetkerninfo
> -64 AUE_NULL OBSOL ogetpagesize
> +64 AUE_NULL COMPAT { int freebsd32_getpagesize( \
> + int32_t dummy); }
> 65 AUE_MSYNC NOPROTO { int msync(void *addr, size_t len, \
> int flags); }
> 66 AUE_VFORK NOPROTO { int vfork(void); }
> @@ -210,7 +214,8 @@
> 100 AUE_GETPRIORITY NOPROTO { int getpriority(int which, int who); }
> 101 AUE_NULL OBSOL osend
> 102 AUE_NULL OBSOL orecv
> -103 AUE_NULL OBSOL osigreturn
> +103 AUE_NULL COMPAT { int freebsd32_sigreturn( \
> + struct ia32_sigcontext3 *sigcntxp); }
> 104 AUE_BIND NOPROTO { int bind(int s, caddr_t name, \
> int namelen); }
> 105 AUE_SETSOCKOPT NOPROTO { int setsockopt(int s, int level, \
> @@ -292,7 +297,8 @@
> ; 155 is initialized by the NFS code, if present.
> ; XXX this is a problem!!!
> 155 AUE_NFS_SVC UNIMPL nfssvc
> -156 AUE_GETDIRENTRIES OBSOL ogetdirentries
> +156 AUE_GETDIRENTRIES COMPAT { int freebsd32_getdirentries(int fd, \
> + char *buf, u_int count, uint32_t *basep); }
> 157 AUE_STATFS COMPAT4 { int freebsd32_statfs(char *path, \
> struct statfs32 *buf); }
> 158 AUE_FSTATFS COMPAT4 { int freebsd32_fstatfs(int fd, \
>
> Modified: head/sys/compat/ia32/ia32_genassym.c
> ==============================================================================
> --- head/sys/compat/ia32/ia32_genassym.c Fri Apr 1 06:28:21 2011 (r220237)
> +++ head/sys/compat/ia32/ia32_genassym.c Fri Apr 1 11:16:29 2011 (r220238)
> @@ -13,6 +13,9 @@ __FBSDID("$FreeBSD$");
>
> ASSYM(IA32_SIGF_HANDLER, offsetof(struct ia32_sigframe, sf_ah));
> ASSYM(IA32_SIGF_UC, offsetof(struct ia32_sigframe, sf_uc));
> +#ifdef COMPAT_43
> +ASSYM(IA32_SIGF_SC, offsetof(struct ia32_sigframe3, sf_siginfo.si_sc));
> +#endif
> ASSYM(IA32_UC_GS, offsetof(struct ia32_ucontext, uc_mcontext.mc_gs));
> ASSYM(IA32_UC_FS, offsetof(struct ia32_ucontext, uc_mcontext.mc_fs));
> ASSYM(IA32_UC_ES, offsetof(struct ia32_ucontext, uc_mcontext.mc_es));
>
> Modified: head/sys/compat/ia32/ia32_signal.h
> ==============================================================================
> --- head/sys/compat/ia32/ia32_signal.h Fri Apr 1 06:28:21 2011 (r220237)
> +++ head/sys/compat/ia32/ia32_signal.h Fri Apr 1 11:16:29 2011 (r220238)
> @@ -112,7 +112,7 @@ struct ia32_ucontext4 {
> };
> #endif
>
> -#ifdef COMPAT_FREEBSD3
> +#ifdef COMPAT_43
> struct ia32_sigcontext3 {
> u_int32_t sc_onstack;
> u_int32_t sc_mask;
> @@ -165,7 +165,7 @@ struct ia32_sigframe {
> struct siginfo32 sf_si; /* = *sf_siginfo (SA_SIGINFO case) */
> };
>
> -#ifdef COMPAT_FREEBSD3
> +#ifdef COMPAT_43
> struct ia32_siginfo3 {
> struct ia32_sigcontext3 si_sc;
> int si_signo;
> @@ -186,10 +186,15 @@ struct ksiginfo;
> struct image_params;
> extern char ia32_sigcode[];
> extern char freebsd4_ia32_sigcode[];
> +extern char ia32_osigcode[];
> +extern char lcall_tramp;
> extern int sz_ia32_sigcode;
> extern int sz_freebsd4_ia32_sigcode;
> -extern void ia32_sendsig(sig_t, struct ksiginfo *, sigset_t *);
> -extern void ia32_setregs(struct thread *td, struct image_params *imgp,
> +extern int sz_ia32_osigcode;
> +extern int sz_lcall_tramp;
> +void ia32_sendsig(sig_t, struct ksiginfo *, sigset_t *);
> +void ia32_setregs(struct thread *td, struct image_params *imgp,
> u_long stack);
> +int setup_lcall_gate(void);
>
> #endif
>
> Modified: head/sys/compat/ia32/ia32_sysvec.c
> ==============================================================================
> --- head/sys/compat/ia32/ia32_sysvec.c Fri Apr 1 06:28:21 2011 (r220237)
> +++ head/sys/compat/ia32/ia32_sysvec.c Fri Apr 1 11:16:29 2011 (r220238)
> @@ -95,14 +95,12 @@ CTASSERT(sizeof(struct ia32_sigframe4) =
>
> extern const char *freebsd32_syscallnames[];
>
> -static void ia32_fixlimit(struct rlimit *rl, int which);
> -
> SYSCTL_NODE(_compat, OID_AUTO, ia32, CTLFLAG_RW, 0, "ia32 mode");
>
> static u_long ia32_maxdsiz = IA32_MAXDSIZ;
> SYSCTL_ULONG(_compat_ia32, OID_AUTO, maxdsiz, CTLFLAG_RW, &ia32_maxdsiz, 0, "");
> TUNABLE_ULONG("compat.ia32.maxdsiz", &ia32_maxdsiz);
> -static u_long ia32_maxssiz = IA32_MAXSSIZ;
> +u_long ia32_maxssiz = IA32_MAXSSIZ;
> SYSCTL_ULONG(_compat_ia32, OID_AUTO, maxssiz, CTLFLAG_RW, &ia32_maxssiz, 0, "");
> TUNABLE_ULONG("compat.ia32.maxssiz", &ia32_maxssiz);
> static u_long ia32_maxvmem = IA32_MAXVMEM;
> @@ -206,7 +204,7 @@ elf32_dump_thread(struct thread *td __un
> {
> }
>
> -static void
> +void
> ia32_fixlimit(struct rlimit *rl, int which)
> {
>
>
> Modified: head/sys/compat/ia32/ia32_util.h
> ==============================================================================
> --- head/sys/compat/ia32/ia32_util.h Fri Apr 1 06:28:21 2011 (r220237)
> +++ head/sys/compat/ia32/ia32_util.h Fri Apr 1 11:16:29 2011 (r220238)
> @@ -58,5 +58,6 @@
> struct syscall_args;
> int ia32_fetch_syscall_args(struct thread *td, struct syscall_args *sa);
> void ia32_set_syscall_retval(struct thread *, int);
> +void ia32_fixlimit(struct rlimit *rl, int which);
>
> #endif
>
> Modified: head/sys/ia64/ia32/ia32_misc.c
> ==============================================================================
> --- head/sys/ia64/ia32/ia32_misc.c Fri Apr 1 06:28:21 2011 (r220237)
> +++ head/sys/ia64/ia32/ia32_misc.c Fri Apr 1 11:16:29 2011 (r220238)
> @@ -48,3 +48,14 @@ freebsd32_sysarch(struct thread *td, str
>
> return (EOPNOTSUPP);
> }
> +
> +#ifdef COMPAT_43
> +int
> +ofreebsd32_getpagesize(struct thread *td,
> + struct ofreebsd32_getpagesize_args *uap)
> +{
> +
> + td->td_retval[0] = IA32_PAGE_SIZE;
> + return (0);
> +}
> +#endif
>
> Modified: head/sys/ia64/ia32/ia32_signal.c
> ==============================================================================
> --- head/sys/ia64/ia32/ia32_signal.c Fri Apr 1 06:28:21 2011 (r220237)
> +++ head/sys/ia64/ia32/ia32_signal.c Fri Apr 1 11:16:29 2011 (r220238)
> @@ -92,6 +92,15 @@ x) */
> };
> int sz_ia32_sigcode = sizeof(ia32_sigcode);
>
> +#ifdef COMPAT_43
> +int
> +ofreebsd32_sigreturn(struct thread *td, struct ofreebsd32_sigreturn_args *uap)
> +{
> +
> + return (EOPNOTSUPP);
> +}
> +#endif
> +
> /*
> * Signal sending has not been implemented on ia64. This causes
> * the sigtramp code to not understand the arguments and the application
>
> Modified: head/sys/kern/imgact_aout.c
> ==============================================================================
> --- head/sys/kern/imgact_aout.c Fri Apr 1 06:28:21 2011 (r220237)
> +++ head/sys/kern/imgact_aout.c Fri Apr 1 11:16:29 2011 (r220238)
> @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
> #include <sys/imgact.h>
> #include <sys/imgact_aout.h>
> #include <sys/kernel.h>
> +#include <sys/limits.h>
> #include <sys/lock.h>
> #include <sys/malloc.h>
> #include <sys/mutex.h>
> @@ -52,9 +53,18 @@ __FBSDID("$FreeBSD$");
> #include <vm/vm_object.h>
> #include <vm/vm_param.h>
>
> +#ifdef __amd64__
> +#include <compat/freebsd32/freebsd32_signal.h>
> +#include <compat/freebsd32/freebsd32_util.h>
> +#include <compat/freebsd32/freebsd32_proto.h>
> +#include <compat/freebsd32/freebsd32_syscall.h>
> +#include <compat/ia32/ia32_signal.h>
> +#endif
> +
> static int exec_aout_imgact(struct image_params *imgp);
> static int aout_fixup(register_t **stack_base, struct image_params *imgp);
>
> +#if defined(__i386__)
> struct sysentvec aout_sysvec = {
> .sv_size = SYS_MAXSYSCALL,
> .sv_table = sysent,
> @@ -83,31 +93,69 @@ struct sysentvec aout_sysvec = {
> .sv_setregs = exec_setregs,
> .sv_fixlimit = NULL,
> .sv_maxssiz = NULL,
> - .sv_flags = SV_ABI_FREEBSD | SV_AOUT |
> -#if defined(__i386__)
> - SV_IA32 | SV_ILP32
> -#else
> -#error Choose SV_XXX flags for the platform
> -#endif
> - ,
> + .sv_flags = SV_ABI_FREEBSD | SV_AOUT | SV_IA32 | SV_ILP32,
> .sv_set_syscall_retval = cpu_set_syscall_retval,
> .sv_fetch_syscall_args = cpu_fetch_syscall_args,
> .sv_syscallnames = syscallnames,
> .sv_schedtail = NULL,
> };
>
> +#elif defined(__amd64__)
> +
> +#define AOUT32_USRSTACK 0xbfc0000
> +#define AOUT32_PS_STRINGS \
> + (AOUT32_USRSTACK - sizeof(struct freebsd32_ps_strings))
> +
> +extern const char *freebsd32_syscallnames[];
> +extern u_long ia32_maxssiz;
> +
> +struct sysentvec aout_sysvec = {
> + .sv_size = FREEBSD32_SYS_MAXSYSCALL,
> + .sv_table = freebsd32_sysent,
> + .sv_mask = 0,
> + .sv_sigsize = 0,
> + .sv_sigtbl = NULL,
> + .sv_errsize = 0,
> + .sv_errtbl = NULL,
> + .sv_transtrap = NULL,
> + .sv_fixup = aout_fixup,
> + .sv_sendsig = ia32_sendsig,
> + .sv_sigcode = ia32_sigcode,
> + .sv_szsigcode = &sz_ia32_sigcode,
> + .sv_prepsyscall = NULL,
> + .sv_name = "FreeBSD a.out",
> + .sv_coredump = NULL,
> + .sv_imgact_try = NULL,
> + .sv_minsigstksz = MINSIGSTKSZ,
> + .sv_pagesize = IA32_PAGE_SIZE,
> + .sv_minuser = 0,
> + .sv_maxuser = AOUT32_USRSTACK,
> + .sv_usrstack = AOUT32_USRSTACK,
> + .sv_psstrings = AOUT32_PS_STRINGS,
> + .sv_stackprot = VM_PROT_ALL,
> + .sv_copyout_strings = freebsd32_copyout_strings,
> + .sv_setregs = ia32_setregs,
> + .sv_fixlimit = ia32_fixlimit,
> + .sv_maxssiz = &ia32_maxssiz,
> + .sv_flags = SV_ABI_FREEBSD | SV_AOUT | SV_IA32 | SV_ILP32,
> + .sv_set_syscall_retval = ia32_set_syscall_retval,
> + .sv_fetch_syscall_args = ia32_fetch_syscall_args,
> + .sv_syscallnames = freebsd32_syscallnames,
> +};
> +#else
> +#error "Port me"
> +#endif
> +
> static int
> -aout_fixup(stack_base, imgp)
> - register_t **stack_base;
> - struct image_params *imgp;
> +aout_fixup(register_t **stack_base, struct image_params *imgp)
> {
>
> - return (suword(--(*stack_base), imgp->args->argc));
> + *(char **)stack_base -= sizeof(uint32_t);
> + return (suword(*stack_base, imgp->args->argc));
> }
>
> static int
> -exec_aout_imgact(imgp)
> - struct image_params *imgp;
> +exec_aout_imgact(struct image_params *imgp)
> {
> const struct exec *a_out = (const struct exec *) imgp->image_header;
> struct vmspace *vmspace;
> @@ -175,7 +223,14 @@ exec_aout_imgact(imgp)
> a_out->a_entry >= virtual_offset + a_out->a_text ||
>
> /* text and data size must each be page rounded */
> - a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK)
> + a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK
> +
> +#ifdef __amd64__
> + ||
> + /* overflows */
> + virtual_offset + a_out->a_text + a_out->a_data + bss_size > UINT_MAX
> +#endif
> + )
> return (-1);
>
> /* text + data can't exceed file size */
>
> Modified: head/sys/kern/vfs_syscalls.c
> ==============================================================================
> --- head/sys/kern/vfs_syscalls.c Fri Apr 1 06:28:21 2011 (r220237)
> +++ head/sys/kern/vfs_syscalls.c Fri Apr 1 11:16:29 2011 (r220238)
> @@ -3898,14 +3898,20 @@ struct ogetdirentries_args {
> };
> #endif
> int
> -ogetdirentries(td, uap)
> - struct thread *td;
> - register struct ogetdirentries_args /* {
> - int fd;
> - char *buf;
> - u_int count;
> - long *basep;
> - } */ *uap;
> +ogetdirentries(struct thread *td, struct ogetdirentries_args *uap)
> +{
> + long loff;
> + int error;
> +
> + error = kern_ogetdirentries(td, uap, &loff);
> + if (error == 0)
> + error = copyout(&loff, uap->basep, sizeof(long));
> + return (error);
> +}
> +
> +int
> +kern_ogetdirentries(struct thread *td, struct ogetdirentries_args *uap,
> + long *ploff)
> {
> struct vnode *vp;
> struct file *fp;
> @@ -4024,9 +4030,10 @@ unionread:
> }
> VOP_UNLOCK(vp, 0);
> VFS_UNLOCK_GIANT(vfslocked);
> - error = copyout(&loff, uap->basep, sizeof(long));
> fdrop(fp, td);
> td->td_retval[0] = uap->count - auio.uio_resid;
> + if (error == 0)
> + *ploff = loff;
> return (error);
> }
> #endif /* COMPAT_43 */
>
> Modified: head/sys/modules/Makefile
> ==============================================================================
> --- head/sys/modules/Makefile Fri Apr 1 06:28:21 2011 (r220237)
> +++ head/sys/modules/Makefile Fri Apr 1 11:16:29 2011 (r220238)
> @@ -518,6 +518,7 @@ _snc= snc
>
> .if ${MACHINE_CPUARCH} == "amd64"
> _aac= aac
> +_aout= aout
> _acpi= acpi
> .if ${MK_CRYPT} != "no" || defined(ALL_MODULES)
> _aesni= aesni
>
> Modified: head/sys/sys/syscallsubr.h
> ==============================================================================
> --- head/sys/sys/syscallsubr.h Fri Apr 1 06:28:21 2011 (r220237)
> +++ head/sys/sys/syscallsubr.h Fri Apr 1 11:16:29 2011 (r220238)
> @@ -52,6 +52,7 @@ struct kld_file_stat;
> struct ksiginfo;
> struct sendfile_args;
> struct thr_param;
> +struct ogetdirentries_args;
>
> int kern___getcwd(struct thread *td, u_char *buf, enum uio_seg bufseg,
> u_int buflen);
> @@ -143,6 +144,8 @@ int kern_msgsnd(struct thread *, int, co
> int kern_msgrcv(struct thread *, int, void *, size_t, long, int, long *);
> int kern_nanosleep(struct thread *td, struct timespec *rqt,
> struct timespec *rmt);
> +int kern_ogetdirentries(struct thread *td, struct ogetdirentries_args *uap,
> + long *ploff);
> int kern_open(struct thread *td, char *path, enum uio_seg pathseg,
> int flags, int mode);
> int kern_openat(struct thread *td, int fd, char *path,
--
a13x
More information about the svn-src-head
mailing list