summaryrefslogtreecommitdiffstats
path: root/sys/amd64/ia32
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>2003-05-14 04:10:49 +0000
committerpeter <peter@FreeBSD.org>2003-05-14 04:10:49 +0000
commit770abdbb9c2f22fc13f2dc8ee14024fe29933651 (patch)
tree65e4ac1aca11723390006ee027d286f8177b0ec6 /sys/amd64/ia32
parent94122e1008f06fc69b00745c3556ee667db464b3 (diff)
downloadFreeBSD-src-770abdbb9c2f22fc13f2dc8ee14024fe29933651.zip
FreeBSD-src-770abdbb9c2f22fc13f2dc8ee14024fe29933651.tar.gz
Add BASIC i386 binary support for the amd64 kernel. This is largely
stolen from the ia64/ia32 code (indeed there was a repocopy), but I've redone the MD parts and added and fixed a few essential syscalls. It is sufficient to run i386 binaries like /bin/ls, /usr/bin/id (dynamic) and p4. The ia64 code has not implemented signal delivery, so I had to do that. Before you say it, yes, this does need to go in a common place. But we're in a freeze at the moment and I didn't want to risk breaking ia64. I will sort this out after the freeze so that the common code is in a common place. On the AMD64 side, this required adding segment selector context switch support and some other support infrastructure. The %fs/%gs etc code is hairy because loading %gs will clobber the kernel's current MSR_GSBASE setting. The segment selectors are not used by the kernel, so they're only changed at context switch time or when changing modes. This still needs to be optimized. Approved by: re (amd64/* blanket)
Diffstat (limited to 'sys/amd64/ia32')
-rw-r--r--sys/amd64/ia32/ia32_exception.S69
-rw-r--r--sys/amd64/ia32/ia32_genassym.c24
-rw-r--r--sys/amd64/ia32/ia32_misc.c116
-rw-r--r--sys/amd64/ia32/ia32_signal.c559
-rw-r--r--sys/amd64/ia32/ia32_signal.h164
-rw-r--r--sys/amd64/ia32/ia32_sigtramp.S87
-rw-r--r--sys/amd64/ia32/ia32_syscall.c275
-rw-r--r--sys/amd64/ia32/ia32_sysvec.c225
-rw-r--r--sys/amd64/ia32/ia32_util.h2
-rw-r--r--sys/amd64/ia32/syscalls.master16
10 files changed, 1374 insertions, 163 deletions
diff --git a/sys/amd64/ia32/ia32_exception.S b/sys/amd64/ia32/ia32_exception.S
new file mode 100644
index 0000000..aa901ef
--- /dev/null
+++ b/sys/amd64/ia32/ia32_exception.S
@@ -0,0 +1,69 @@
+/*-
+ * Copyright (c) 2003 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.
+ * 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 <machine/asmacros.h>
+
+#include "assym.s"
+
+#define IDTVEC(name) ALIGN_TEXT; .globl __CONCAT(X,name); \
+ .type __CONCAT(X,name),@function; __CONCAT(X,name):
+
+ .text
+/*
+ * Call gate entry for FreeBSD ELF and Linux/NetBSD syscall (int 0x80)
+ *
+ * This is a SDT_SYSIDT entry point (unlike the i386 port) so that we
+ * can do a swapgs before enabling interrupts. This is critical because
+ * if we took an interrupt before swapgs, the interrupt code would see
+ * that it originated in supervisor mode and skip the swapgs.
+ */
+ SUPERALIGN_TEXT
+IDTVEC(int0x80_syscall)
+ swapgs
+ sti
+ pushq $2 /* sizeof "int 0x80" */
+ subq $TF_ERR,%rsp /* skip over tf_trapno */
+ movq %rdi,TF_RDI(%rsp)
+ movq %rsi,TF_RSI(%rsp)
+ movq %rdx,TF_RDX(%rsp)
+ movq %rcx,TF_RCX(%rsp)
+ movq %r8,TF_R8(%rsp)
+ movq %r9,TF_R9(%rsp)
+ movq %rax,TF_RAX(%rsp)
+ movq %rbx,TF_RBX(%rsp)
+ movq %rbp,TF_RBP(%rsp)
+ movq %r10,TF_R10(%rsp)
+ movq %r11,TF_R11(%rsp)
+ movq %r12,TF_R12(%rsp)
+ movq %r13,TF_R13(%rsp)
+ movq %r14,TF_R14(%rsp)
+ movq %r15,TF_R15(%rsp)
+ FAKE_MCOUNT(13*4(%rsp))
+ call ia32_syscall
+ MEXITCOUNT
+ jmp doreti
diff --git a/sys/amd64/ia32/ia32_genassym.c b/sys/amd64/ia32/ia32_genassym.c
new file mode 100644
index 0000000..2134a44
--- /dev/null
+++ b/sys/amd64/ia32/ia32_genassym.c
@@ -0,0 +1,24 @@
+/* $FreeBSD$ */
+
+#include "opt_compat.h"
+
+#include <sys/param.h>
+#include <sys/assym.h>
+#include <sys/systm.h>
+#include <sys/signal.h>
+
+#include <amd64/ia32/ia32_signal.h>
+
+ASSYM(IA32_SIGF_HANDLER, offsetof(struct ia32_sigframe, sf_ah));
+ASSYM(IA32_SIGF_UC, offsetof(struct ia32_sigframe, sf_uc));
+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));
+ASSYM(IA32_UC_DS, offsetof(struct ia32_ucontext, uc_mcontext.mc_ds));
+#ifdef COMPAT_FREEBSD4
+ASSYM(IA32_SIGF_UC4, offsetof(struct ia32_sigframe, sf_uc));
+ASSYM(IA32_UC4_GS, offsetof(struct ia32_ucontext4, uc_mcontext.mc_gs));
+ASSYM(IA32_UC4_FS, offsetof(struct ia32_ucontext4, uc_mcontext.mc_fs));
+ASSYM(IA32_UC4_ES, offsetof(struct ia32_ucontext4, uc_mcontext.mc_es));
+ASSYM(IA32_UC4_DS, offsetof(struct ia32_ucontext4, uc_mcontext.mc_ds));
+#endif
diff --git a/sys/amd64/ia32/ia32_misc.c b/sys/amd64/ia32/ia32_misc.c
index c1cdd20..9ef02c5 100644
--- a/sys/amd64/ia32/ia32_misc.c
+++ b/sys/amd64/ia32/ia32_misc.c
@@ -74,9 +74,9 @@
#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>
+#include <amd64/ia32/ia32_util.h>
+#include <amd64/ia32/ia32.h>
+#include <amd64/ia32/ia32_proto.h>
static const char ia32_emul_path[] = "/compat/ia32";
/*
@@ -439,6 +439,7 @@ ia32_execve(struct thread *td, struct ia32_execve_args *uap)
return execve(td, &ap);
}
+#ifdef __ia64__
static int
ia32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
int prot, int fd, off_t pos)
@@ -485,6 +486,7 @@ ia32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
return (0);
}
}
+#endif
int
ia32_mmap(struct thread *td, struct ia32_mmap_args *uap)
@@ -497,6 +499,7 @@ ia32_mmap(struct thread *td, struct ia32_mmap_args *uap)
int fd = uap->fd;
off_t pos = (uap->poslo
| ((off_t)uap->poshi << 32));
+#ifdef __ia64__
vm_size_t pageoff;
int error;
@@ -567,6 +570,7 @@ ia32_mmap(struct thread *td, struct ia32_mmap_args *uap)
addr = start;
len = end - start;
}
+#endif
ap.addr = (void *) addr;
ap.len = len;
@@ -653,6 +657,83 @@ ia32_select(struct thread *td, struct ia32_select_args *uap)
return (select(td, (struct select_args *) uap));
}
+struct kevent32 {
+ u_int32_t ident; /* identifier for this event */
+ short filter; /* filter for event */
+ u_short flags;
+ u_int fflags;
+ int32_t data;
+ u_int32_t udata; /* opaque user data identifier */
+};
+
+int
+ia32_kevent(struct thread *td, struct ia32_kevent_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct timespec32 ts32;
+ struct timespec ts;
+ struct kevent32 ks32;
+ struct kevent *ks;
+ struct kevent_args a;
+ int i;
+
+ sg = stackgap_init();
+
+ a.fd = uap->fd;
+ a.changelist = uap->changelist;
+ a.nchanges = uap->nchanges;
+ a.eventlist = uap->eventlist;
+ a.nevents = uap->nevents;
+ a.timeout = NULL;
+
+ if (uap->timeout) {
+ a.timeout = stackgap_alloc(&sg, sizeof(struct timespec));
+ error = copyin(uap->timeout, &ts32, sizeof(ts32));
+ if (error)
+ return (error);
+ CP(ts32, ts, tv_sec);
+ CP(ts32, ts, tv_nsec);
+ error = copyout(&ts, (void *)(uintptr_t)a.timeout, sizeof(ts));
+ if (error)
+ return (error);
+ }
+ if (uap->changelist) {
+ a.changelist = (struct kevent *)stackgap_alloc(&sg, uap->nchanges * sizeof(struct kevent));
+ for (i = 0; i < uap->nchanges; i++) {
+ error = copyin(&uap->changelist[i], &ks32, sizeof(ks32));
+ if (error)
+ return (error);
+ ks = (struct kevent *)(uintptr_t)&a.changelist[i];
+ CP(ks32, *ks, ident);
+ CP(ks32, *ks, filter);
+ CP(ks32, *ks, flags);
+ CP(ks32, *ks, fflags);
+ CP(ks32, *ks, data);
+ PTRIN_CP(ks32, *ks, udata);
+ }
+ }
+ if (uap->eventlist) {
+ a.eventlist = stackgap_alloc(&sg, uap->nevents * sizeof(struct kevent));
+ }
+ error = kevent(td, &a);
+ if (uap->eventlist && error > 0) {
+ for (i = 0; i < error; i++) {
+ ks = &a.eventlist[i];
+ CP(*ks, ks32, ident);
+ CP(*ks, ks32, filter);
+ CP(*ks, ks32, flags);
+ CP(*ks, ks32, fflags);
+ CP(*ks, ks32, data);
+ PTROUT_CP(*ks, ks32, udata);
+ error = copyout(&ks32, &uap->eventlist[i], sizeof(ks32));
+ if (error)
+ return (error);
+ }
+ }
+ return error;
+}
+
int
ia32_gettimeofday(struct thread *td, struct ia32_gettimeofday_args *uap)
{
@@ -1287,6 +1368,35 @@ ia32_sigaction(struct thread *td, struct ia32_sigaction_args *uap)
return (error);
}
+#ifdef COMPAT_FREEBSD4
+int
+freebsd4_ia32_sigaction(struct thread *td, struct freebsd4_ia32_sigaction_args *uap)
+{
+ struct sigaction32 s32;
+ struct sigaction sa, osa, *sap;
+ int error;
+
+ if (uap->act) {
+ error = copyin(uap->act, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ sa.sa_handler = PTRIN(s32.sa_u);
+ CP(s32, sa, sa_flags);
+ CP(s32, sa, sa_mask);
+ sap = &sa;
+ } else
+ sap = NULL;
+ error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
+ if (error != 0 && uap->oact != NULL) {
+ s32.sa_u = PTROUT(osa.sa_handler);
+ CP(osa, s32, sa_flags);
+ CP(osa, s32, sa_mask);
+ error = copyout(&s32, uap->oact, sizeof(s32));
+ }
+ return (error);
+}
+#endif
+
#if 0
int
diff --git a/sys/amd64/ia32/ia32_signal.c b/sys/amd64/ia32/ia32_signal.c
new file mode 100644
index 0000000..ae966a5
--- /dev/null
+++ b/sys/amd64/ia32/ia32_signal.c
@@ -0,0 +1,559 @@
+/*-
+ * Copyright (c) 2003 Peter Wemm
+ * Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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 "opt_compat.h"
+
+#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 <amd64/ia32/ia32_util.h>
+#include <amd64/ia32/ia32_proto.h>
+#include <amd64/ia32/ia32_signal.h>
+#include <machine/psl.h>
+#include <machine/segments.h>
+#include <machine/specialreg.h>
+#include <machine/frame.h>
+#include <machine/md_var.h>
+#include <machine/pcb.h>
+#include <machine/cpufunc.h>
+
+#ifdef COMPAT_FREEBSD4
+static void freebsd4_ia32_sendsig(sig_t, int, sigset_t *, u_long);
+#endif
+static void ia32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp);
+static int ia32_set_fpcontext(struct thread *td, const struct ia32_mcontext *mcp);
+
+extern int _ucode32sel, _udatasel;
+
+#define CS_SECURE(cs) (ISPL(cs) == SEL_UPL)
+#define EFL_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
+
+static void
+ia32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp)
+{
+ struct savefpu *addr;
+
+ /*
+ * XXX mc_fpstate might be misaligned, since its declaration is not
+ * unportabilized using __attribute__((aligned(16))) like the
+ * declaration of struct savemm, and anyway, alignment doesn't work
+ * for auto variables since we don't use gcc's pessimal stack
+ * alignment. Work around this by abusing the spare fields after
+ * mcp->mc_fpstate.
+ *
+ * XXX unpessimize most cases by only aligning when fxsave might be
+ * called, although this requires knowing too much about
+ * npxgetregs()'s internals.
+ */
+ addr = (struct savefpu *)&mcp->mc_fpstate;
+ if (td == PCPU_GET(fpcurthread) && ((uintptr_t)(void *)addr & 0xF)) {
+ do
+ addr = (void *)((char *)addr + 4);
+ while ((uintptr_t)(void *)addr & 0xF);
+ }
+ mcp->mc_ownedfp = npxgetregs(td, addr);
+ if (addr != (struct savefpu *)&mcp->mc_fpstate) {
+ bcopy(addr, &mcp->mc_fpstate, sizeof(mcp->mc_fpstate));
+ bzero(&mcp->mc_spare2, sizeof(mcp->mc_spare2));
+ }
+ mcp->mc_fpformat = npxformat();
+}
+
+static int
+ia32_set_fpcontext(struct thread *td, const struct ia32_mcontext *mcp)
+{
+ struct savefpu *addr;
+
+ if (mcp->mc_fpformat == _MC_FPFMT_NODEV)
+ return (0);
+ else if (mcp->mc_fpformat != _MC_FPFMT_XMM)
+ return (EINVAL);
+ else if (mcp->mc_ownedfp == _MC_FPOWNED_NONE)
+ /* We don't care what state is left in the FPU or PCB. */
+ fpstate_drop(td);
+ else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU ||
+ mcp->mc_ownedfp == _MC_FPOWNED_PCB) {
+ /* XXX align as above. */
+ addr = (struct savefpu *)&mcp->mc_fpstate;
+ if (td == PCPU_GET(fpcurthread) &&
+ ((uintptr_t)(void *)addr & 0xF)) {
+ do
+ addr = (void *)((char *)addr + 4);
+ while ((uintptr_t)(void *)addr & 0xF);
+ bcopy(&mcp->mc_fpstate, addr, sizeof(mcp->mc_fpstate));
+ }
+ /*
+ * XXX we violate the dubious requirement that npxsetregs()
+ * be called with interrupts disabled.
+ */
+ npxsetregs(td, addr);
+ /*
+ * Don't bother putting things back where they were in the
+ * misaligned case, since we know that the caller won't use
+ * them again.
+ */
+ } else
+ return (EINVAL);
+ return (0);
+}
+
+/*
+ * Send an interrupt to process.
+ *
+ * Stack is set up to allow sigcode stored
+ * at top to call routine, followed by kcall
+ * to sigreturn routine below. After sigreturn
+ * resets the signal mask, the stack, and the
+ * frame pointer, it returns to the user
+ * specified pc, psl.
+ */
+#ifdef COMPAT_FREEBSD4
+static void
+freebsd4_ia32_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
+{
+ struct ia32_sigframe4 sf, *sfp;
+ struct proc *p;
+ struct thread *td;
+ struct sigacts *psp;
+ struct trapframe *regs;
+ int oonstack;
+
+ td = curthread;
+ p = td->td_proc;
+ PROC_LOCK_ASSERT(p, MA_OWNED);
+ psp = p->p_sigacts;
+ regs = td->td_frame;
+ oonstack = sigonstack(regs->tf_rsp);
+
+ /* Save user context. */
+ bzero(&sf, sizeof(sf));
+ sf.sf_uc.uc_sigmask = *mask;
+ sf.sf_uc.uc_stack.ss_sp = (uintptr_t)p->p_sigstk.ss_sp;
+ sf.sf_uc.uc_stack.ss_size = p->p_sigstk.ss_size;
+ sf.sf_uc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK)
+ ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
+ sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
+ sf.sf_uc.uc_mcontext.mc_gs = rgs();
+ sf.sf_uc.uc_mcontext.mc_fs = rfs();
+ __asm __volatile("movl %%es,%0" : "=rm" (sf.sf_uc.uc_mcontext.mc_es));
+ __asm __volatile("movl %%ds,%0" : "=rm" (sf.sf_uc.uc_mcontext.mc_ds));
+ sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi;
+ sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi;
+ sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp;
+ sf.sf_uc.uc_mcontext.mc_isp = regs->tf_rsp; /* XXX */
+ sf.sf_uc.uc_mcontext.mc_ebx = regs->tf_rbx;
+ sf.sf_uc.uc_mcontext.mc_edx = regs->tf_rdx;
+ sf.sf_uc.uc_mcontext.mc_ecx = regs->tf_rcx;
+ sf.sf_uc.uc_mcontext.mc_eax = regs->tf_rax;
+ sf.sf_uc.uc_mcontext.mc_trapno = regs->tf_trapno;
+ sf.sf_uc.uc_mcontext.mc_err = regs->tf_err;
+ sf.sf_uc.uc_mcontext.mc_eip = regs->tf_rip;
+ sf.sf_uc.uc_mcontext.mc_cs = regs->tf_cs;
+ sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags;
+ sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp;
+ sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss;
+
+ /* Allocate space for the signal handler context. */
+ if ((p->p_flag & P_ALTSTACK) != 0 && !oonstack &&
+ SIGISMEMBER(psp->ps_sigonstack, sig)) {
+ sfp = (struct ia32_sigframe4 *)(p->p_sigstk.ss_sp +
+ p->p_sigstk.ss_size - sizeof(sf));
+ } else
+ sfp = (struct ia32_sigframe4 *)regs->tf_rsp - 1;
+ PROC_UNLOCK(p);
+
+ /* 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_ucontext = (register_t)&sfp->sf_uc;
+ PROC_LOCK(p);
+ if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
+ /* Signal handler installed with SA_SIGINFO. */
+ sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si;
+ sf.sf_ah = (u_int32_t)(uintptr_t)catcher;
+
+ /* Fill in POSIX parts */
+ sf.sf_si.si_signo = sig;
+ sf.sf_si.si_code = code;
+ sf.sf_si.si_addr = regs->tf_addr;
+ } else {
+ /* Old FreeBSD-style arguments. */
+ sf.sf_siginfo = code;
+ sf.sf_addr = regs->tf_addr;
+ sf.sf_ah = (u_int32_t)(uintptr_t)catcher;
+ }
+ PROC_UNLOCK(p);
+
+ /*
+ * Copy the sigframe out to the user's stack.
+ */
+ if (copyout(&sf, sfp, sizeof(*sfp)) != 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)sfp;
+ regs->tf_rip = PS_STRINGS - sz_freebsd4_ia32_sigcode;
+ regs->tf_rflags &= ~PSL_T;
+ regs->tf_cs = _ucode32sel;
+ regs->tf_ss = _udatasel;
+ load_ds(_udatasel);
+ td->td_pcb->pcb_ds = _udatasel;
+ load_es(_udatasel);
+ td->td_pcb->pcb_es = _udatasel;
+ /* leave user %fs and %gs untouched */
+ PROC_LOCK(p);
+}
+#endif /* COMPAT_FREEBSD4 */
+
+void
+ia32_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
+{
+ struct ia32_sigframe sf, *sfp;
+ struct proc *p;
+ struct thread *td;
+ struct sigacts *psp;
+ char *sp;
+ struct trapframe *regs;
+ int oonstack;
+
+ td = curthread;
+ p = td->td_proc;
+ PROC_LOCK_ASSERT(p, MA_OWNED);
+ psp = p->p_sigacts;
+#ifdef COMPAT_FREEBSD4
+ if (SIGISMEMBER(psp->ps_freebsd4, sig)) {
+ freebsd4_ia32_sendsig(catcher, sig, mask, code);
+ return;
+ }
+#endif
+ regs = td->td_frame;
+ oonstack = sigonstack(regs->tf_rsp);
+
+ /* Save user context. */
+ bzero(&sf, sizeof(sf));
+ sf.sf_uc.uc_sigmask = *mask;
+ sf.sf_uc.uc_stack.ss_sp = (uintptr_t)p->p_sigstk.ss_sp;
+ sf.sf_uc.uc_stack.ss_size = p->p_sigstk.ss_size;
+ sf.sf_uc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK)
+ ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
+ sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
+ sf.sf_uc.uc_mcontext.mc_gs = rgs();
+ sf.sf_uc.uc_mcontext.mc_fs = rfs();
+ __asm __volatile("movl %%es,%0" : "=rm" (sf.sf_uc.uc_mcontext.mc_es));
+ __asm __volatile("movl %%ds,%0" : "=rm" (sf.sf_uc.uc_mcontext.mc_ds));
+ sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi;
+ sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi;
+ sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp;
+ sf.sf_uc.uc_mcontext.mc_isp = regs->tf_rsp; /* XXX */
+ sf.sf_uc.uc_mcontext.mc_ebx = regs->tf_rbx;
+ sf.sf_uc.uc_mcontext.mc_edx = regs->tf_rdx;
+ sf.sf_uc.uc_mcontext.mc_ecx = regs->tf_rcx;
+ sf.sf_uc.uc_mcontext.mc_eax = regs->tf_rax;
+ sf.sf_uc.uc_mcontext.mc_trapno = regs->tf_trapno;
+ sf.sf_uc.uc_mcontext.mc_err = regs->tf_err;
+ sf.sf_uc.uc_mcontext.mc_eip = regs->tf_rip;
+ sf.sf_uc.uc_mcontext.mc_cs = regs->tf_cs;
+ sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags;
+ sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp;
+ sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss;
+ sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* magic */
+ ia32_get_fpcontext(td, &sf.sf_uc.uc_mcontext);
+ fpstate_drop(td);
+
+ /* Allocate space for the signal handler context. */
+ if ((p->p_flag & P_ALTSTACK) != 0 && !oonstack &&
+ SIGISMEMBER(psp->ps_sigonstack, sig)) {
+ sp = p->p_sigstk.ss_sp +
+ p->p_sigstk.ss_size - sizeof(sf);
+ } else
+ sp = (char *)regs->tf_rsp - sizeof(sf);
+ /* Align to 16 bytes. */
+ sfp = (struct ia32_sigframe *)((uintptr_t)sp & ~0xF);
+ PROC_UNLOCK(p);
+
+ /* 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_ucontext = (register_t)&sfp->sf_uc;
+ PROC_LOCK(p);
+ if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
+ /* Signal handler installed with SA_SIGINFO. */
+ sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si;
+ sf.sf_ah = (u_int32_t)(uintptr_t)catcher;
+
+ /* Fill in POSIX parts */
+ sf.sf_si.si_signo = sig;
+ sf.sf_si.si_code = code;
+ sf.sf_si.si_addr = regs->tf_addr;
+ } else {
+ /* Old FreeBSD-style arguments. */
+ sf.sf_siginfo = code;
+ sf.sf_addr = regs->tf_err;
+ sf.sf_ah = (u_int32_t)(uintptr_t)catcher;
+ }
+ PROC_UNLOCK(p);
+
+ /*
+ * Copy the sigframe out to the user's stack.
+ */
+ if (copyout(&sf, sfp, sizeof(*sfp)) != 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)sfp;
+ regs->tf_rip = PS_STRINGS - *(p->p_sysent->sv_szsigcode);
+ regs->tf_rflags &= ~PSL_T;
+ regs->tf_cs = _ucode32sel;
+ regs->tf_ss = _udatasel;
+ load_ds(_udatasel);
+ td->td_pcb->pcb_ds = _udatasel;
+ load_es(_udatasel);
+ td->td_pcb->pcb_es = _udatasel;
+ /* leave user %fs and %gs untouched */
+ PROC_LOCK(p);
+}
+
+/*
+ * System call to cleanup state after a signal
+ * has been taken. Reset signal mask and
+ * stack state from context left by sendsig (above).
+ * Return to previous pc and psl as specified by
+ * context left by sendsig. Check carefully to
+ * make sure that the user has not modified the
+ * state to gain improper privileges.
+ */
+#ifdef COMPAT_FREEBSD4
+/*
+ * MPSAFE
+ */
+int
+freebsd4_ia32_sigreturn(td, uap)
+ struct thread *td;
+ struct freebsd4_ia32_sigreturn_args /* {
+ const struct freebsd4_ucontext *sigcntxp;
+ } */ *uap;
+{
+ struct ia32_ucontext4 uc;
+ struct proc *p = td->td_proc;
+ struct trapframe *regs;
+ const struct ia32_ucontext4 *ucp;
+ int cs, eflags, error;
+
+ error = copyin(uap->sigcntxp, &uc, sizeof(uc));
+ if (error != 0)
+ return (error);
+ ucp = &uc;
+ regs = td->td_frame;
+ eflags = ucp->uc_mcontext.mc_eflags;
+ /*
+ * Don't allow users to change privileged or reserved flags.
+ */
+ /*
+ * XXX do allow users to change the privileged flag PSL_RF.
+ * The cpu sets PSL_RF in tf_eflags for faults. Debuggers
+ * should sometimes set it there too. tf_eflags is kept in
+ * the signal context during signal handling and there is no
+ * other place to remember it, so the PSL_RF bit may be
+ * corrupted by the signal handler without us knowing.
+ * Corruption of the PSL_RF bit at worst causes one more or
+ * one less debugger trap, so allowing it is fairly harmless.
+ */
+ if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) {
+ printf("freebsd4_ia32_sigreturn: eflags = 0x%x\n", eflags);
+ return (EINVAL);
+ }
+
+ /*
+ * Don't allow users to load a valid privileged %cs. Let the
+ * hardware check for invalid selectors, excess privilege in
+ * other selectors, invalid %eip's and invalid %esp's.
+ */
+ cs = ucp->uc_mcontext.mc_cs;
+ if (!CS_SECURE(cs)) {
+ printf("freebsd4_sigreturn: cs = 0x%x\n", cs);
+ trapsignal(td, SIGBUS, T_PROTFLT);
+ return (EINVAL);
+ }
+
+ /* Segment selectors restored by sigtramp.S */
+ regs->tf_rdi = ucp->uc_mcontext.mc_edi;
+ regs->tf_rsi = ucp->uc_mcontext.mc_esi;
+ regs->tf_rbp = ucp->uc_mcontext.mc_ebp;
+ regs->tf_rbx = ucp->uc_mcontext.mc_ebx;
+ regs->tf_rdx = ucp->uc_mcontext.mc_edx;
+ regs->tf_rcx = ucp->uc_mcontext.mc_ecx;
+ regs->tf_rax = ucp->uc_mcontext.mc_eax;
+ regs->tf_trapno = ucp->uc_mcontext.mc_trapno;
+ regs->tf_err = ucp->uc_mcontext.mc_err;
+ regs->tf_rip = ucp->uc_mcontext.mc_eip;
+ regs->tf_cs = cs;
+ regs->tf_rflags = ucp->uc_mcontext.mc_eflags;
+ regs->tf_rsp = ucp->uc_mcontext.mc_esp;
+ regs->tf_ss = ucp->uc_mcontext.mc_ss;
+
+ PROC_LOCK(p);
+ td->td_sigmask = ucp->uc_sigmask;
+ SIG_CANTMASK(td->td_sigmask);
+ signotify(td);
+ PROC_UNLOCK(p);
+ return (EJUSTRETURN);
+}
+#endif /* COMPAT_FREEBSD4 */
+
+/*
+ * MPSAFE
+ */
+int
+ia32_sigreturn(td, uap)
+ struct thread *td;
+ struct ia32_sigreturn_args /* {
+ const struct ia32_ucontext *sigcntxp;
+ } */ *uap;
+{
+ struct ia32_ucontext uc;
+ struct proc *p = td->td_proc;
+ struct trapframe *regs;
+ const struct ia32_ucontext *ucp;
+ int cs, eflags, error, ret;
+
+ error = copyin(uap->sigcntxp, &uc, sizeof(uc));
+ if (error != 0)
+ return (error);
+ ucp = &uc;
+ regs = td->td_frame;
+ eflags = ucp->uc_mcontext.mc_eflags;
+ /*
+ * Don't allow users to change privileged or reserved flags.
+ */
+ /*
+ * XXX do allow users to change the privileged flag PSL_RF.
+ * The cpu sets PSL_RF in tf_eflags for faults. Debuggers
+ * should sometimes set it there too. tf_eflags is kept in
+ * the signal context during signal handling and there is no
+ * other place to remember it, so the PSL_RF bit may be
+ * corrupted by the signal handler without us knowing.
+ * Corruption of the PSL_RF bit at worst causes one more or
+ * one less debugger trap, so allowing it is fairly harmless.
+ */
+ if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) {
+ printf("ia32_sigreturn: eflags = 0x%x\n", eflags);
+ return (EINVAL);
+ }
+
+ /*
+ * Don't allow users to load a valid privileged %cs. Let the
+ * hardware check for invalid selectors, excess privilege in
+ * other selectors, invalid %eip's and invalid %esp's.
+ */
+ cs = ucp->uc_mcontext.mc_cs;
+ if (!CS_SECURE(cs)) {
+ printf("sigreturn: cs = 0x%x\n", cs);
+ trapsignal(td, SIGBUS, T_PROTFLT);
+ return (EINVAL);
+ }
+
+ ret = ia32_set_fpcontext(td, &ucp->uc_mcontext);
+ if (ret != 0)
+ return (ret);
+
+ /* Segment selectors restored by sigtramp.S */
+ regs->tf_rdi = ucp->uc_mcontext.mc_edi;
+ regs->tf_rsi = ucp->uc_mcontext.mc_esi;
+ regs->tf_rbp = ucp->uc_mcontext.mc_ebp;
+ regs->tf_rbx = ucp->uc_mcontext.mc_ebx;
+ regs->tf_rdx = ucp->uc_mcontext.mc_edx;
+ regs->tf_rcx = ucp->uc_mcontext.mc_ecx;
+ regs->tf_rax = ucp->uc_mcontext.mc_eax;
+ regs->tf_trapno = ucp->uc_mcontext.mc_trapno;
+ regs->tf_err = ucp->uc_mcontext.mc_err;
+ regs->tf_rip = ucp->uc_mcontext.mc_eip;
+ regs->tf_cs = cs;
+ regs->tf_rflags = ucp->uc_mcontext.mc_eflags;
+ regs->tf_rsp = ucp->uc_mcontext.mc_esp;
+ regs->tf_ss = ucp->uc_mcontext.mc_ss;
+
+ PROC_LOCK(p);
+ td->td_sigmask = ucp->uc_sigmask;
+ SIG_CANTMASK(td->td_sigmask);
+ signotify(td);
+ PROC_UNLOCK(p);
+ return (EJUSTRETURN);
+}
diff --git a/sys/amd64/ia32/ia32_signal.h b/sys/amd64/ia32/ia32_signal.h
new file mode 100644
index 0000000..f251e72
--- /dev/null
+++ b/sys/amd64/ia32/ia32_signal.h
@@ -0,0 +1,164 @@
+/*-
+ * Copyright (c) 1999 Marcel Moolenaar
+ * Copyright (c) 2003 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$
+ */
+
+struct ia32_sigaltstack {
+ u_int32_t ss_sp; /* signal stack base */
+ u_int32_t ss_size; /* signal stack length */
+ int ss_flags; /* SS_DISABLE and/or SS_ONSTACK */
+};
+
+/* XXX should be 640 bytes long; check and see if __packed is needed */
+struct ia32_mcontext {
+ int mc_onstack; /* XXX - sigcontext compat. */
+ int mc_gs; /* machine state (struct trapframe) */
+ int mc_fs;
+ int mc_es;
+ int mc_ds;
+ int mc_edi;
+ int mc_esi;
+ int mc_ebp;
+ int mc_isp;
+ int mc_ebx;
+ int mc_edx;
+ int mc_ecx;
+ int mc_eax;
+ int mc_trapno;
+ int mc_err;
+ int mc_eip;
+ int mc_cs;
+ int mc_eflags;
+ int mc_esp;
+ int mc_ss;
+ int mc_len; /* sizeof(struct ia32_mcontext) */
+ /* We use the same values for fpformat and ownedfp */
+ int mc_fpformat;
+ int mc_ownedfp;
+ int mc_spare1[1]; /* align next field to 16 bytes */
+ /*
+ * See <machine/npx.h> for the internals of mc_fpstate[].
+ */
+ int mc_fpstate[128] __aligned(16);
+ int mc_spare2[8];
+};
+
+/* XXX should be 704 bytes long; check and see if __packed is needed */
+struct ia32_ucontext {
+ sigset_t uc_sigmask;
+ struct ia32_mcontext uc_mcontext;
+ u_int32_t uc_link;
+ struct ia32_sigaltstack uc_stack;
+ int uc_flags;
+ int __spare__[4];
+};
+
+
+#if defined(COMPAT_FREEBSD4)
+struct ia32_mcontext4 {
+ int mc_onstack; /* XXX - sigcontext compat. */
+ int mc_gs; /* machine state (struct trapframe) */
+ int mc_fs;
+ int mc_es;
+ int mc_ds;
+ int mc_edi;
+ int mc_esi;
+ int mc_ebp;
+ int mc_isp;
+ int mc_ebx;
+ int mc_edx;
+ int mc_ecx;
+ int mc_eax;
+ int mc_trapno;
+ int mc_err;
+ int mc_eip;
+ int mc_cs;
+ int mc_eflags;
+ int mc_esp;
+ int mc_ss;
+ int mc_fpregs[28];
+ int __spare__[17];
+};
+
+struct ia32_ucontext4 {
+ sigset_t uc_sigmask;
+ struct ia32_mcontext4 uc_mcontext;
+ u_int32_t uc_link;
+ struct ia32_sigaltstack uc_stack;
+ int __spare__[8];
+};
+#endif
+
+/*
+ * Signal frames, arguments passed to application signal handlers.
+ */
+union ia32_sigval {
+ int sigval_int;
+ u_int32_t sigval_ptr;
+};
+struct ia32_siginfo {
+ int si_signo; /* signal number */
+ int si_errno; /* errno association */
+ int si_code; /* signal code */
+ int32_t si_pid; /* sending process */
+ u_int32_t si_uid; /* sender's ruid */
+ int si_status; /* exit value */
+ u_int32_t si_addr; /* faulting instruction */
+ union ia32_sigval si_value; /* signal value */
+ int32_t si_band; /* band event for SIGPOLL */
+ int __spare__[7]; /* gimme some slack */
+};
+
+#ifdef COMPAT_FREEBSD4
+struct ia32_sigframe4 {
+ u_int32_t sf_signum;
+ u_int32_t sf_siginfo; /* code or pointer to sf_si */
+ u_int32_t sf_ucontext; /* points to sf_uc */
+ u_int32_t sf_addr; /* undocumented 4th arg */
+ u_int32_t sf_ah; /* action/handler pointer */
+ struct ia32_ucontext4 sf_uc; /* = *sf_ucontext */
+ struct ia32_siginfo sf_si; /* = *sf_siginfo (SA_SIGINFO case) */
+};
+#endif
+
+struct ia32_sigframe {
+ u_int32_t sf_signum;
+ u_int32_t sf_siginfo; /* code or pointer to sf_si */
+ u_int32_t sf_ucontext; /* points to sf_uc */
+ u_int32_t sf_addr; /* undocumented 4th arg */
+ u_int32_t sf_ah; /* action/handler pointer */
+ struct ia32_ucontext sf_uc; /* = *sf_ucontext */
+ struct ia32_siginfo sf_si; /* = *sf_siginfo (SA_SIGINFO case) */
+};
+
+extern char ia32_sigcode[];
+extern char freebsd4_ia32_sigcode[];
+extern int sz_ia32_sigcode;
+extern int sz_freebsd4_ia32_sigcode;
+extern void ia32_sendsig(sig_t, int, sigset_t *, u_long);
diff --git a/sys/amd64/ia32/ia32_sigtramp.S b/sys/amd64/ia32/ia32_sigtramp.S
new file mode 100644
index 0000000..2e9f73d
--- /dev/null
+++ b/sys/amd64/ia32/ia32_sigtramp.S
@@ -0,0 +1,87 @@
+/*-
+ * Copyright (c) 2003 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.
+ * 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 "opt_compat.h"
+
+#include <machine/asmacros.h>
+#include <sys/syscall.h>
+
+#include "ia32_assym.h"
+
+ .text
+ .code32
+/*
+ * Signal trampoline, copied to top of user stack
+ */
+ ALIGN_TEXT
+ .globl ia32_sigcode
+ia32_sigcode:
+ calll *IA32_SIGF_HANDLER(%esp)
+ leal IA32_SIGF_UC(%esp),%eax /* get ucontext */
+ pushl %eax
+ movl IA32_UC_GS(%eax),%gs /* restore %gs */
+ movl IA32_UC_FS(%eax),%fs /* restore %fs */
+ movl IA32_UC_ES(%eax),%es /* restore %es */
+ movl IA32_UC_DS(%eax),%ds /* restore %ds */
+ movl $SYS_sigreturn,%eax
+ pushl %eax /* junk to fake return addr. */
+ int $0x80 /* enter kernel with args */
+ /* on stack */
+1:
+ jmp 1b
+
+#ifdef COMPAT_FREEBSD4
+ ALIGN_TEXT
+freebsd4_ia32_sigcode:
+ calll *IA32_SIGF_HANDLER(%esp)
+ leal IA32_SIGF_UC4(%esp),%eax/* get ucontext */
+ pushl %eax
+ movl IA32_UC4_GS(%eax),%gs /* restore %gs */
+ movl IA32_UC4_FS(%eax),%fs /* restore %fs */
+ movl IA32_UC4_ES(%eax),%es /* restore %es */
+ movl IA32_UC4_DS(%eax),%ds /* restore %ds */
+ movl $344,%eax /* 4.x SYS_sigreturn */
+ pushl %eax /* junk to fake return addr. */
+ int $0x80 /* enter kernel with args */
+ /* on stack */
+1:
+ jmp 1b
+#endif
+
+ ALIGN_TEXT
+esigcode:
+
+ .data
+ .globl sz_ia32_sigcode
+sz_ia32_sigcode:
+ .long esigcode-ia32_sigcode
+#ifdef COMPAT_FREEBSD4
+ .globl sz_freebsd4_ia32_sigcode
+sz_freebsd4_ia32_sigcode:
+ .long esigcode-freebsd4_ia32_sigcode
+#endif
diff --git a/sys/amd64/ia32/ia32_syscall.c b/sys/amd64/ia32/ia32_syscall.c
new file mode 100644
index 0000000..dee52b0
--- /dev/null
+++ b/sys/amd64/ia32/ia32_syscall.c
@@ -0,0 +1,275 @@
+/*-
+ * Copyright (C) 1994, David Greenman
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the University of Utah, and William Jolitz.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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$
+ */
+
+/*
+ * 386 Trap and System call handling
+ */
+
+#include "opt_clock.h"
+#include "opt_cpu.h"
+#include "opt_isa.h"
+#include "opt_ktrace.h"
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/pioctl.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/resourcevar.h>
+#include <sys/signalvar.h>
+#include <sys/syscall.h>
+#include <sys/sysctl.h>
+#include <sys/sysent.h>
+#include <sys/uio.h>
+#include <sys/vmmeter.h>
+#ifdef KTRACE
+#include <sys/ktrace.h>
+#endif
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_map.h>
+#include <vm/vm_page.h>
+#include <vm/vm_extern.h>
+
+#include <machine/cpu.h>
+#include <machine/md_var.h>
+
+#include <amd64/isa/icu.h>
+#include <amd64/isa/intr_machdep.h>
+
+#define IDTVEC(name) __CONCAT(X,name)
+
+extern inthand_t IDTVEC(int0x80_syscall), IDTVEC(rsvd);
+
+void ia32_syscall(struct trapframe frame); /* Called from asm code */
+
+void
+ia32_syscall(struct trapframe frame)
+{
+ caddr_t params;
+ int i;
+ struct sysent *callp;
+ struct thread *td = curthread;
+ struct proc *p = td->td_proc;
+ register_t orig_tf_rflags;
+ u_int sticks;
+ int error;
+ int narg;
+ u_int32_t args[8];
+ u_int64_t args64[8];
+ u_int code;
+
+ /*
+ * note: PCPU_LAZY_INC() can only be used if we can afford
+ * occassional inaccuracy in the count.
+ */
+ cnt.v_syscall++;
+
+ sticks = td->td_sticks;
+ td->td_frame = &frame;
+ if (td->td_ucred != p->p_ucred)
+ cred_update_thread(td);
+ params = (caddr_t)frame.tf_rsp + sizeof(u_int32_t);
+ code = frame.tf_rax;
+ orig_tf_rflags = frame.tf_rflags;
+
+ if (p->p_sysent->sv_prepsyscall) {
+ /*
+ * The prep code is MP aware.
+ */
+ (*p->p_sysent->sv_prepsyscall)(&frame, args, &code, &params);
+ } else {
+ /*
+ * Need to check if this is a 32 bit or 64 bit syscall.
+ * fuword is MP aware.
+ */
+ if (code == SYS_syscall) {
+ /*
+ * Code is first argument, followed by actual args.
+ */
+ code = fuword32(params);
+ params += sizeof(int);
+ } else if (code == SYS___syscall) {
+ /*
+ * Like syscall, but code is a quad, so as to maintain
+ * quad alignment for the rest of the arguments.
+ * We use a 32-bit fetch in case params is not
+ * aligned.
+ */
+ code = fuword32(params);
+ params += sizeof(quad_t);
+ }
+ }
+
+ if (p->p_sysent->sv_mask)
+ code &= p->p_sysent->sv_mask;
+
+ if (code >= p->p_sysent->sv_size)
+ callp = &p->p_sysent->sv_table[0];
+ else
+ callp = &p->p_sysent->sv_table[code];
+
+ narg = callp->sy_narg & SYF_ARGMASK;
+
+ /*
+ * copyin and the ktrsyscall()/ktrsysret() code is MP-aware
+ */
+ if (params != NULL && narg != 0)
+ error = copyin(params, (caddr_t)args,
+ (u_int)(narg * sizeof(int)));
+ else
+ error = 0;
+
+ for (i = 0; i < narg; i++)
+ args64[i] = args[i];
+
+#ifdef KTRACE
+ if (KTRPOINT(td, KTR_SYSCALL))
+ ktrsyscall(code, narg, args64);
+#endif
+ /*
+ * Try to run the syscall without Giant if the syscall
+ * is MP safe.
+ */
+ if ((callp->sy_narg & SYF_MPSAFE) == 0)
+ mtx_lock(&Giant);
+
+ if (error == 0) {
+ td->td_retval[0] = 0;
+ td->td_retval[1] = frame.tf_rdx;
+
+ STOPEVENT(p, S_SCE, narg);
+
+ error = (*callp->sy_call)(td, args64);
+ }
+
+ switch (error) {
+ case 0:
+ frame.tf_rax = td->td_retval[0];
+ frame.tf_rdx = td->td_retval[1];
+ frame.tf_rflags &= ~PSL_C;
+ break;
+
+ case ERESTART:
+ /*
+ * Reconstruct pc, assuming lcall $X,y is 7 bytes,
+ * int 0x80 is 2 bytes. We saved this in tf_err.
+ */
+ frame.tf_rip -= frame.tf_err;
+ break;
+
+ case EJUSTRETURN:
+ break;
+
+ default:
+ if (p->p_sysent->sv_errsize) {
+ if (error >= p->p_sysent->sv_errsize)
+ error = -1; /* XXX */
+ else
+ error = p->p_sysent->sv_errtbl[error];
+ }
+ frame.tf_rax = error;
+ frame.tf_rflags |= PSL_C;
+ break;
+ }
+
+ /*
+ * Release Giant if we previously set it.
+ */
+ if ((callp->sy_narg & SYF_MPSAFE) == 0)
+ mtx_unlock(&Giant);
+
+ /*
+ * Traced syscall.
+ */
+ if (orig_tf_rflags & PSL_T) {
+ frame.tf_rflags &= ~PSL_T;
+ trapsignal(td, SIGTRAP, 0);
+ }
+
+ /*
+ * Handle reschedule and other end-of-syscall issues
+ */
+ userret(td, &frame, sticks);
+
+#ifdef KTRACE
+ if (KTRPOINT(td, KTR_SYSRET))
+ ktrsysret(code, error, td->td_retval[0]);
+#endif
+
+ /*
+ * This works because errno is findable through the
+ * register set. If we ever support an emulation where this
+ * is not the case, this code will need to be revisited.
+ */
+ STOPEVENT(p, S_SCX, code);
+
+#ifdef DIAGNOSTIC
+ cred_free_thread(td);
+#endif
+ WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
+ (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???");
+ mtx_assert(&sched_lock, MA_NOTOWNED);
+ mtx_assert(&Giant, MA_NOTOWNED);
+}
+
+
+static void
+ia32_syscall_enable(void *dummy)
+{
+
+ setidt(0x80, &IDTVEC(int0x80_syscall), SDT_SYSIGT, SEL_UPL, 0);
+}
+
+static void
+ia32_syscall_disable(void *dummy)
+{
+
+ setidt(0x80, &IDTVEC(rsvd), SDT_SYSIGT, SEL_KPL, 0);
+}
+
+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);
diff --git a/sys/amd64/ia32/ia32_sysvec.c b/sys/amd64/ia32/ia32_sysvec.c
index 18f4ee2..684677a 100644
--- a/sys/amd64/ia32/ia32_sysvec.c
+++ b/sys/amd64/ia32/ia32_sysvec.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2002 Doug Rabson
+ * Copyright (c) 2003 Peter Wemm
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,6 +27,8 @@
* $FreeBSD$
*/
+#include "opt_compat.h"
+
#define __ELF_WORD_SIZE 32
#include <sys/param.h>
@@ -60,12 +63,16 @@
#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 <amd64/ia32/ia32_util.h>
+#include <amd64/ia32/ia32_proto.h>
+#include <amd64/ia32/ia32_signal.h>
+#include <machine/psl.h>
+#include <machine/segments.h>
+#include <machine/specialreg.h>
#include <machine/frame.h>
#include <machine/md_var.h>
+#include <machine/pcb.h>
+#include <machine/cpufunc.h>
static register_t *ia32_copyout_strings(struct image_params *imgp);
static void ia32_setregs(struct thread *td, u_long entry, u_long stack,
@@ -73,21 +80,6 @@ static void ia32_setregs(struct thread *td, u_long entry, u_long stack,
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,
@@ -98,24 +90,26 @@ struct sysentvec ia32_freebsd_sysvec = {
NULL,
NULL,
elf32_freebsd_fixup,
- sendsig,
+ ia32_sendsig,
ia32_sigcode,
- &ia32_szsigcode,
+ &sz_ia32_sigcode,
NULL,
- "FreeBSD ELF",
+ "FreeBSD ELF32",
elf32_coredump,
NULL,
MINSIGSTKSZ,
- 4096,
+ PAGE_SIZE,
0,
- IA32_USRSTACK,
- IA32_USRSTACK,
- IA32_PS_STRINGS,
+ USRSTACK,
+ USRSTACK,
+ PS_STRINGS,
VM_PROT_ALL,
ia32_copyout_strings,
ia32_setregs
};
+
+
static Elf32_Brandinfo ia32_brand_info = {
ELFOSABI_FREEBSD,
EM_386,
@@ -129,6 +123,8 @@ SYSINIT(ia32, SI_SUB_EXEC, SI_ORDER_ANY,
(sysinit_cfunc_t) elf32_insert_brand_entry,
&ia32_brand_info);
+extern int _ucode32sel, _udatasel;
+
static register_t *
ia32_copyout_strings(struct image_params *imgp)
{
@@ -143,7 +139,7 @@ ia32_copyout_strings(struct image_params *imgp)
* 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;
+ arginfo = (struct ia32_ps_strings *)PS_STRINGS;
szsigcode = *(imgp->proc->p_sysent->sv_szsigcode);
destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE -
roundup((ARG_MAX - imgp->stringspace), sizeof(char *));
@@ -190,7 +186,6 @@ ia32_copyout_strings(struct image_params *imgp)
stringp = imgp->stringbase;
argc = imgp->argc;
envc = imgp->envc;
-
/*
* Copy out strings - arguments and environment.
*/
@@ -234,135 +229,61 @@ ia32_copyout_strings(struct image_params *imgp)
return ((register_t *)stack_base);
}
-static void
-ia32_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings)
+/*
+ * Clear registers on exec
+ */
+void
+ia32_setregs(td, entry, stack, ps_strings)
+ 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;
+ struct trapframe *regs = td->td_frame;
+ struct pcb *pcb = td->td_pcb;
+ u_int64_t pc;
+ register_t s;
+
+ wrmsr(MSR_FSBASE, 0);
+ wrmsr(MSR_KGSBASE, 0); /* User value while we're in the kernel */
+ pcb->pcb_fsbase = 0;
+ pcb->pcb_gsbase = 0;
+ pcb->pcb_kgsbase = rdmsr(MSR_GSBASE);
+ load_ds(_udatasel);
+ load_es(_udatasel);
+ load_fs(_udatasel);
+ s = intr_disable();
+ pc = rdmsr(MSR_GSBASE);
+ load_gs(_udatasel); /* Clobbers kernel %GS.base */
+ wrmsr(MSR_GSBASE, pc);
+ intr_restore(s);
+ pcb->pcb_ds = _udatasel;
+ pcb->pcb_es = _udatasel;
+ pcb->pcb_fs = _udatasel;
+ pcb->pcb_gs = _udatasel;
+
+ bzero((char *)regs, sizeof(struct trapframe));
+ regs->tf_rip = entry;
+ regs->tf_rsp = stack;
+ regs->tf_rflags = PSL_USER | (regs->tf_rflags & PSL_T);
+ regs->tf_ss = _udatasel;
+ regs->tf_cs = _ucode32sel;
+ regs->tf_rbx = ps_strings;
/*
- * Make sure that we restore the entire trapframe after an
- * execve.
+ * Arrange to trap the next npx or `fwait' instruction (see npx.c
+ * for why fwait must be trapped at least if there is an npx or an
+ * emulator). This is mainly to handle the case where npx0 is not
+ * configured, since the npx routines normally set up the trap
+ * otherwise. It should be done only at boot time, but doing it
+ * here allows modifying `npx_exists' for testing the emulator on
+ * systems with an npx.
*/
- 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
+ load_cr0(rcr0() | CR0_MP | CR0_TS);
- /*
- * 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;
+ fpstate_drop(td);
- /*
- * XXX - Linux emulator
- * Make sure sure edx is 0x0 on entry. Linux binaries depend
- * on it.
- */
+ /* Return via doreti so that we can change to a different %cs */
+ pcb->pcb_flags |= PCB_FULLCTX;
td->td_retval[1] = 0;
}
diff --git a/sys/amd64/ia32/ia32_util.h b/sys/amd64/ia32/ia32_util.h
index 23f2aba..20a5b1e 100644
--- a/sys/amd64/ia32/ia32_util.h
+++ b/sys/amd64/ia32/ia32_util.h
@@ -44,7 +44,7 @@ struct ia32_ps_strings {
int ps_nenvstr; /* the number of environment strings */
};
-#define IA32_USRSTACK (4L*1024*1024*1024 - PAGE_SIZE)
+#define IA32_USRSTACK USRSTACK
#define IA32_PS_STRINGS (IA32_USRSTACK - sizeof(struct ia32_ps_strings))
static __inline caddr_t stackgap_init(void);
diff --git a/sys/amd64/ia32/syscalls.master b/sys/amd64/ia32/syscalls.master
index 508fdf7..042bf00 100644
--- a/sys/amd64/ia32/syscalls.master
+++ b/sys/amd64/ia32/syscalls.master
@@ -37,8 +37,8 @@
#include <sys/sysent.h>
#include <sys/sysproto.h>
#include <sys/mount.h>
-#include <ia64/ia32/ia32.h>
-#include <ia64/ia32/ia32_proto.h>
+#include <amd64/ia32/ia32.h>
+#include <amd64/ia32/ia32_proto.h>
; Reserved/unimplemented system calls in the range 0-150 inclusive
; are reserved for use in future Berkeley releases.
@@ -484,11 +484,11 @@
340 MNOPROTO POSIX { int sigprocmask(int how, const sigset_t *set, \
sigset_t *oset); }
341 MNOPROTO POSIX { int sigsuspend(const sigset_t *sigmask); }
-342 STD POSIX { int ia32_sigaction(int sig, \
+342 COMPAT4 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); }
+344 MCOMPAT4 BSD { int ia32_sigreturn(const struct __ucontext *sigcntxp); }
345 UNIMPL NOHIDE sigtimedwait
346 UNIMPL NOHIDE sigwaitinfo
347 MNOPROTO BSD { int __acl_get_file(const char *path, \
@@ -521,7 +521,7 @@
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, \
+363 MSTD BSD { int ia32_kevent(int fd, \
const struct kevent *changelist, int nchanges, \
struct kevent *eventlist, int nevents, \
const struct timespec *timeout); }
@@ -586,8 +586,10 @@
413 UNIMPL BSD extattr_get_link
414 UNIMPL BSD extattr_delete_link
415 UNIMPL BSD __mac_execve
-416 UNIMPL BSD newsigreturn
-417 UNIMPL BSD newsigaction
+416 MSTD BSD { int ia32_sigreturn(const struct ia32_ucontext *sigcntxp); }
+417 STD POSIX { int ia32_sigaction(int sig, \
+ struct sigaction32 *act, \
+ struct sigaction32 *oact); }
418 UNIMPL BSD __xstat
419 UNIMPL BSD __xfstat
420 UNIMPL BSD __xlstat
OpenPOWER on IntegriCloud