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)
This commit is contained in:
Peter Wemm 2003-05-14 04:10:49 +00:00
parent 5d5ca6d75e
commit d85631c4ac
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=114987
32 changed files with 1983 additions and 387 deletions

View File

@ -106,6 +106,12 @@ ENTRY(cpu_switch)
pushfq /* PSL */
popq PCB_RFLAGS(%r8)
/* Save kernel %gs.base */
movl $MSR_GSBASE,%ecx
rdmsr
movl %eax,PCB_KGSBASE(%r8)
movl %edx,PCB_KGSBASE+4(%r8)
/* Save userland %fs */
movl $MSR_FSBASE,%ecx
rdmsr
@ -118,6 +124,12 @@ ENTRY(cpu_switch)
movl %eax,PCB_GSBASE(%r8)
movl %edx,PCB_GSBASE+4(%r8)
/* Save segment selector numbers */
movl %ds,PCB_DS(%r8)
movl %es,PCB_ES(%r8)
movl %fs,PCB_FS(%r8)
movl %gs,PCB_GS(%r8)
/* have we used fp, and need a save? */
cmpq %rdi,PCPU(FPCURTHREAD)
jne 1f
@ -160,6 +172,18 @@ sw1:
*/
movq TD_PCB(%rsi),%r8
/* Restore segment selector numbers */
movl PCB_DS(%r8),%ds
movl PCB_ES(%r8),%es
movl PCB_FS(%r8),%fs
movl PCB_GS(%r8),%gs
/* Restore kernel %gs.base */
movl $MSR_GSBASE,%ecx
movl PCB_KGSBASE(%r8),%eax
movl PCB_KGSBASE+4(%r8),%edx
wrmsr
/* Restore userland %fs */
movl $MSR_FSBASE,%ecx
movl PCB_FSBASE(%r8),%eax

View File

@ -217,40 +217,6 @@ IDTVEC(page)
sti
jmp alltraps_pushregs_no_rdi
/*
* 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 syscall
MEXITCOUNT
jmp doreti
/*
* Fast syscall entry point. We enter here with just our new %cs/%ss set,
* and the new privilige level. We are still running on the old user stack
@ -353,6 +319,7 @@ ENTRY(fork_trampoline)
*/
.text
SUPERALIGN_TEXT
.globl doreti
.type doreti,@function
doreti:
FAKE_MCOUNT(bintr) /* init "from" bintr -> doreti */

View File

@ -125,6 +125,11 @@ ASSYM(PCB_RIP, offsetof(struct pcb, pcb_rip));
ASSYM(PCB_RFLAGS, offsetof(struct pcb, pcb_rflags));
ASSYM(PCB_FSBASE, offsetof(struct pcb, pcb_fsbase));
ASSYM(PCB_GSBASE, offsetof(struct pcb, pcb_gsbase));
ASSYM(PCB_KGSBASE, offsetof(struct pcb, pcb_kgsbase));
ASSYM(PCB_DS, offsetof(struct pcb, pcb_ds));
ASSYM(PCB_ES, offsetof(struct pcb, pcb_es));
ASSYM(PCB_FS, offsetof(struct pcb, pcb_fs));
ASSYM(PCB_GS, offsetof(struct pcb, pcb_gs));
ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags));
ASSYM(PCB_FULLCTX, PCB_FULLCTX);
@ -181,8 +186,10 @@ ASSYM(KCSEL, GSEL(GCODE_SEL, SEL_KPL));
ASSYM(KDSEL, GSEL(GDATA_SEL, SEL_KPL));
ASSYM(KUCSEL, GSEL(GUCODE_SEL, SEL_UPL));
ASSYM(KUDSEL, GSEL(GUDATA_SEL, SEL_UPL));
ASSYM(KUC32SEL, GSEL(GUCODE32_SEL, SEL_UPL));
ASSYM(MSR_FSBASE, MSR_FSBASE);
ASSYM(MSR_GSBASE, MSR_GSBASE);
ASSYM(MSR_KGSBASE, MSR_KGSBASE);
ASSYM(GPROC0_SEL, GPROC0_SEL);

View File

@ -124,12 +124,11 @@ extern void initializecpu(void);
#define EFL_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
static void cpu_startup(void *);
static void fpstate_drop(struct thread *td);
static void get_fpcontext(struct thread *td, mcontext_t *mcp);
static int set_fpcontext(struct thread *td, const mcontext_t *mcp);
SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL)
int _udatasel, _ucodesel;
int _udatasel, _ucodesel, _ucode32sel;
u_long atdevbase;
u_int64_t modulep; /* phys addr of metadata table */
@ -390,6 +389,16 @@ sigreturn(td, uap)
return (EJUSTRETURN);
}
#ifdef COMPAT_FREEBSD4
int
freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap)
{
return sigreturn(td, (struct sigreturn_args *)uap);
}
#endif
/*
* Machine dependent boot() routine
*
@ -467,11 +476,25 @@ exec_setregs(td, entry, stack, ps_strings)
{
struct trapframe *regs = td->td_frame;
struct pcb *pcb = td->td_pcb;
u_int64_t pc;
pcb->pcb_fsbase = 0;
pcb->pcb_gsbase = 0;
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);
critical_enter();
pc = rdmsr(MSR_GSBASE);
load_gs(_udatasel); /* Clobbers kernel %GS.base */
wrmsr(MSR_GSBASE, pc);
critical_exit();
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;
@ -590,7 +613,7 @@ struct soft_segment_descriptor gdt_segs[] = {
0xfffff, /* length - all address space */
SDT_MEMERA, /* segment type */
SEL_UPL, /* segment descriptor priority level */
0, /* segment descriptor present */
1, /* segment descriptor present */
0, /* long */
1, /* default 32 vs 16 bit size */
1 /* limit granularity (byte/page units)*/ },
@ -661,7 +684,7 @@ extern inthand_t
IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(fpusegm),
IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot),
IDTVEC(page), IDTVEC(mchk), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(align),
IDTVEC(xmm), IDTVEC(dblfault), IDTVEC(int0x80_syscall),
IDTVEC(xmm), IDTVEC(dblfault),
IDTVEC(fast_syscall), IDTVEC(fast_syscall32);
void
@ -1232,7 +1255,6 @@ hammer_time(void)
setidt(17, &IDTVEC(align), SDT_SYSIGT, SEL_KPL, 0);
setidt(18, &IDTVEC(mchk), SDT_SYSIGT, SEL_KPL, 0);
setidt(19, &IDTVEC(xmm), SDT_SYSIGT, SEL_KPL, 0);
setidt(0x80, &IDTVEC(int0x80_syscall), SDT_SYSIGT, SEL_UPL, 0);
r_idt.rd_limit = sizeof(idt0) - 1;
r_idt.rd_base = (long) idt;
@ -1290,10 +1312,12 @@ hammer_time(void)
_ucodesel = GSEL(GUCODE_SEL, SEL_UPL);
_udatasel = GSEL(GUDATA_SEL, SEL_UPL);
_ucode32sel = GSEL(GUCODE32_SEL, SEL_UPL);
/* setup proc 0's pcb */
thread0.td_pcb->pcb_flags = 0; /* XXXKSE */
thread0.td_pcb->pcb_cr3 = IdlePML4;
thread0.td_pcb->pcb_kgsbase = (u_int64_t)pc;
thread0.td_frame = &proc0_tf;
}
@ -1613,7 +1637,7 @@ set_fpcontext(struct thread *td, const mcontext_t *mcp)
return (0);
}
static void
void
fpstate_drop(struct thread *td)
{
register_t s;

View File

@ -91,7 +91,7 @@
extern void trap(struct trapframe frame);
extern void syscall(struct trapframe frame);
static int trap_pfault(struct trapframe *, int, vm_offset_t);
static int trap_pfault(struct trapframe *, int);
static void trap_fatal(struct trapframe *, vm_offset_t);
void dblfault_handler(void);
@ -161,13 +161,13 @@ trap(frame)
struct proc *p = td->td_proc;
u_int sticks = 0;
int i = 0, ucode = 0, type, code;
vm_offset_t eva;
atomic_add_int(&cnt.v_trap, 1);
type = frame.tf_trapno;
#ifdef DDB
if (db_active) {
vm_offset_t eva;
eva = (type == T_PAGEFLT ? frame.tf_addr : 0);
trap_fatal(&frame, eva);
goto out;
@ -202,7 +202,6 @@ trap(frame)
}
}
eva = 0;
code = frame.tf_err;
if (type == T_PAGEFLT) {
/*
@ -213,9 +212,8 @@ trap(frame)
* kernel can print out a useful trap message and even get
* to the debugger.
*/
eva = frame.tf_addr;
if (PCPU_GET(spinlocks) != NULL)
trap_fatal(&frame, eva);
trap_fatal(&frame, frame.tf_addr);
}
#ifdef DEVICE_POLLING
@ -261,7 +259,7 @@ trap(frame)
break;
case T_PAGEFLT: /* page fault */
i = trap_pfault(&frame, TRUE, eva);
i = trap_pfault(&frame, TRUE);
if (i == -1)
goto userout;
if (i == 0)
@ -331,7 +329,7 @@ trap(frame)
("kernel trap doesn't have ucred"));
switch (type) {
case T_PAGEFLT: /* page fault */
(void) trap_pfault(&frame, FALSE, eva);
(void) trap_pfault(&frame, FALSE);
goto out;
case T_DNA:
@ -430,7 +428,7 @@ trap(frame)
#endif /* DEV_ISA */
}
trap_fatal(&frame, eva);
trap_fatal(&frame, 0);
goto out;
}
@ -445,7 +443,7 @@ trap(frame)
uprintf("fatal process exception: %s",
trap_msg[type]);
if ((type == T_PAGEFLT) || (type == T_PROTFLT))
uprintf(", fault VA = 0x%lx", eva);
uprintf(", fault VA = 0x%lx", frame.tf_addr);
uprintf("\n");
}
#endif
@ -462,10 +460,9 @@ trap(frame)
}
static int
trap_pfault(frame, usermode, eva)
trap_pfault(frame, usermode)
struct trapframe *frame;
int usermode;
vm_offset_t eva;
{
vm_offset_t va;
struct vmspace *vm = NULL;
@ -474,6 +471,7 @@ trap_pfault(frame, usermode, eva)
vm_prot_t ftype;
struct thread *td = curthread;
struct proc *p = td->td_proc;
vm_offset_t eva = frame->tf_addr;
va = trunc_page(eva);
if (va >= KERNBASE) {
@ -813,4 +811,3 @@ syscall(frame)
mtx_assert(&sched_lock, MA_NOTOWNED);
mtx_assert(&Giant, MA_NOTOWNED);
}

View File

@ -76,7 +76,6 @@
#include <amd64/isa/isa.h>
static void cpu_reset_real(void);
extern int _ucodesel, _udatasel;
/*
* Finish a fork operation, with process p2 nearly set up.
@ -143,6 +142,7 @@ cpu_fork(td1, p2, td2, flags)
* pcb2->pcb_savefpu: cloned above.
* pcb2->pcb_flags: cloned above.
* pcb2->pcb_onfault: cloned above (always NULL here?).
* pcb2->pcb_[fg]sbase: cloned above
*/
/*

View File

@ -22,6 +22,8 @@ machine amd64
cpu HAMMER
ident GENERIC
maxusers 0
options IA32
options COMPAT_FREEBSD4
makeoptions NO_MODULES=not_yet
@ -41,6 +43,10 @@ options NFS_ROOT #NFS usable as root device, requires NFSCLIENT
options INVARIANTS #Enable calls of extra sanity checking
options INVARIANT_SUPPORT #Extra sanity checks of internal structures, required by INVARIANTS
options SYSVMSG
options SYSVSEM
options SYSVSHM
device isa
device pci

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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;
load_cr0(rcr0() | CR0_MP | CR0_TS);
bzero(frame->tf_r, sizeof(frame->tf_r));
bzero(frame->tf_f, sizeof(frame->tf_f));
fpstate_drop(td);
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
/*
* 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;
/*
* 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;
}

View File

@ -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);

View File

@ -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

View File

@ -447,7 +447,6 @@ invlpg(u_long addr)
__asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
}
/* XXX these are replaced with rdmsr/wrmsr */
static __inline u_int
rfs(void)
{
@ -464,6 +463,18 @@ rgs(void)
return (sel);
}
static __inline void
load_ds(u_int sel)
{
__asm __volatile("movl %0,%%ds" : : "rm" (sel));
}
static __inline void
load_es(u_int sel)
{
__asm __volatile("movl %0,%%es" : : "rm" (sel));
}
static __inline void
load_fs(u_int sel)
{

View File

@ -33,9 +33,12 @@
* ELF definitions for the AMD64 architecture.
*/
#include <sys/elf64.h> /* Definitions common to all 64 bit architectures. */
#ifndef __ELF_WORD_SIZE
#define __ELF_WORD_SIZE 64 /* Used by <sys/elf_generic.h> */
#endif
#include <sys/elf32.h> /* Definitions common to all 32 bit architectures. */
#include <sys/elf64.h> /* Definitions common to all 64 bit architectures. */
#include <sys/elf_generic.h>
#define ELF_ARCH EM_X86_64
@ -48,6 +51,13 @@
* The i386 supplement to the SVR4 ABI specification names this "auxv_t",
* but POSIX lays claim to all symbols ending with "_t".
*/
typedef struct { /* Auxiliary vector entry on initial stack */
int a_type; /* Entry type. */
union {
int a_val; /* Integer value. */
} a_un;
} Elf32_Auxinfo;
typedef struct { /* Auxiliary vector entry on initial stack */
long a_type; /* Entry type. */
@ -118,7 +128,11 @@ __ElfType(Auxinfo);
#define R_X86_64_COUNT 16 /* Count of defined relocation types. */
/* Define "machine" characteristics */
#define ELF_TARG_CLASS ELFCLASS64
#if __ELF_WORD_SIZE == 32
#define ELF_TARG_CLASS ELFCLASS32
#else
#define ELF_TARG_CLASS ELFCLASS64
#endif
#define ELF_TARG_DATA ELFDATA2LSB
#define ELF_TARG_MACH EM_X86_64
#define ELF_TARG_VER 1

View File

@ -69,5 +69,6 @@ void pagezero(void *addr);
int is_physical_memory(vm_offset_t addr);
void setidt(int idx, alias_for_inthand_t *func, int typ, int dpl, int ist);
void swi_vm(void *);
void fpstate_drop(struct thread *td);
#endif /* !_MACHINE_MD_VAR_H_ */

View File

@ -59,6 +59,11 @@ struct pcb {
register_t pcb_rflags;
register_t pcb_fsbase;
register_t pcb_gsbase;
register_t pcb_kgsbase;
u_int32_t pcb_ds;
u_int32_t pcb_es;
u_int32_t pcb_fs;
u_int32_t pcb_gs;
struct savefpu pcb_save;
u_long pcb_flags;

View File

@ -166,7 +166,7 @@ struct region_descriptor {
/*
* Size of IDT table
*/
#define NIDT 129 /* 32 reserved, 16 h/w, 0 s/w, linux's 0x80 */
#define NIDT 256 /* 32 reserved, 16 h/w, 0 s/w, linux's 0x80 */
#define NRSVIDT 32 /* reserved entries for cpu exceptions */
/*

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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;
load_cr0(rcr0() | CR0_MP | CR0_TS);
bzero(frame->tf_r, sizeof(frame->tf_r));
bzero(frame->tf_f, sizeof(frame->tf_f));
fpstate_drop(td);
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
/*
* 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;
/*
* 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;
}

View File

@ -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);

View File

@ -8,6 +8,19 @@
# dependency lines other than the first are silently ignored.
#
ia32_genassym.o optional ia32 \
dependency "$S/amd64/ia32/ia32_genassym.c" \
compile-with "${CC} ${CFLAGS:N-fno-common} -c ${.IMPSRC}" \
no-obj no-implicit-rule \
clean "ia32_genassym.o"
#
ia32_assym.h optional ia32 \
dependency "$S/kern/genassym.sh ia32_genassym.o" \
compile-with "sh $S/kern/genassym.sh ia32_genassym.o > ${.TARGET}" \
no-obj no-implicit-rule before-depend \
clean "ia32_assym.h"
#
dev/kbd/atkbd.c optional atkbd
dev/kbd/atkbdc.c optional atkbdc
dev/kbd/kbd.c optional atkbd
@ -64,7 +77,14 @@ amd64/isa/npx.c standard
amd64/pci/pci_cfgreg.c optional pci
amd64/pci/pci_bus.c optional pci
amd64/ia32/ia32_misc.c optional ia32
amd64/ia32/ia32_sysent.c optional ia32
amd64/ia32/ia32_sysvec.c optional ia32
amd64/ia32/ia32_signal.c optional ia32
amd64/ia32/ia32_sigtramp.S optional ia32
amd64/ia32/ia32_exception.S optional ia32
amd64/ia32/ia32_syscall.c optional ia32
kern/imgact_elf32.c optional ia32
# This file tells config what files go into building a kernel,
# files marked standard are always included.

View File

@ -59,3 +59,4 @@ PPC_DEBUG opt_ppc.h
PSM_HOOKRESUME opt_psm.h
PSM_RESETAFTERSUSPEND opt_psm.h
PSM_DEBUG opt_psm.h
IA32