svn commit: r220238 - in head/sys: amd64/ia32 compat/freebsd32 compat/ia32 ia64/ia32 kern modules sys

Konstantin Belousov kib at FreeBSD.org
Fri Apr 1 11:16:31 UTC 2011


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.
  
  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 = &sc;
+	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,


More information about the svn-src-all mailing list