MFC: Implement 32 bit getcontext/setcontext/swapcontext on amd64. Still

stubs for ia64 to keep it compiling.  These are used by 32 bit apps such
as gdb.
This commit is contained in:
sobomax 2007-05-03 11:13:58 +00:00
parent 3036ea3146
commit 9c8e38c33f
3 changed files with 191 additions and 6 deletions

View File

@ -158,6 +158,169 @@ ia32_set_fpcontext(struct thread *td, const struct ia32_mcontext *mcp)
return (0);
}
/*
* Get machine context.
*/
static int
ia32_get_mcontext(struct thread *td, struct ia32_mcontext *mcp, int flags)
{
struct trapframe *tp;
tp = td->td_frame;
PROC_LOCK(curthread->td_proc);
mcp->mc_onstack = sigonstack(tp->tf_rsp);
PROC_UNLOCK(curthread->td_proc);
mcp->mc_gs = td->td_pcb->pcb_gs;
mcp->mc_fs = td->td_pcb->pcb_fs;
mcp->mc_es = td->td_pcb->pcb_es;
mcp->mc_ds = td->td_pcb->pcb_ds;
mcp->mc_edi = tp->tf_rdi;
mcp->mc_esi = tp->tf_rsi;
mcp->mc_ebp = tp->tf_rbp;
mcp->mc_isp = tp->tf_rsp;
if (flags & GET_MC_CLEAR_RET) {
mcp->mc_eax = 0;
mcp->mc_edx = 0;
} else {
mcp->mc_eax = tp->tf_rax;
mcp->mc_edx = tp->tf_rdx;
}
mcp->mc_ebx = tp->tf_rbx;
mcp->mc_ecx = tp->tf_rcx;
mcp->mc_eip = tp->tf_rip;
mcp->mc_cs = tp->tf_cs;
mcp->mc_eflags = tp->tf_rflags;
mcp->mc_esp = tp->tf_rsp;
mcp->mc_ss = tp->tf_ss;
mcp->mc_len = sizeof(*mcp);
ia32_get_fpcontext(td, mcp);
return (0);
}
/*
* Set machine context.
*
* However, we don't set any but the user modifiable flags, and we won't
* touch the cs selector.
*/
static int
ia32_set_mcontext(struct thread *td, const struct ia32_mcontext *mcp)
{
struct trapframe *tp;
long rflags;
int ret;
tp = td->td_frame;
if (mcp->mc_len != sizeof(*mcp))
return (EINVAL);
rflags = (mcp->mc_eflags & PSL_USERCHANGE) |
(tp->tf_rflags & ~PSL_USERCHANGE);
ret = ia32_set_fpcontext(td, mcp);
if (ret != 0)
return (ret);
#if 0 /* XXX deal with load_fs() and friends */
tp->tf_fs = mcp->mc_fs;
tp->tf_es = mcp->mc_es;
tp->tf_ds = mcp->mc_ds;
#endif
tp->tf_rdi = mcp->mc_edi;
tp->tf_rsi = mcp->mc_esi;
tp->tf_rbp = mcp->mc_ebp;
tp->tf_rbx = mcp->mc_ebx;
tp->tf_rdx = mcp->mc_edx;
tp->tf_rcx = mcp->mc_ecx;
tp->tf_rax = mcp->mc_eax;
/* trapno, err */
tp->tf_rip = mcp->mc_eip;
tp->tf_rflags = rflags;
tp->tf_rsp = mcp->mc_esp;
tp->tf_ss = mcp->mc_ss;
#if 0 /* XXX deal with load_gs() and friends */
td->td_pcb->pcb_gs = mcp->mc_gs;
#endif
td->td_pcb->pcb_flags |= PCB_FULLCTX;
return (0);
}
/*
* The first two fields of a ucontext_t are the signal mask and
* the machine context. The next field is uc_link; we want to
* avoid destroying the link when copying out contexts.
*/
#define UC_COPY_SIZE offsetof(struct ia32_ucontext, uc_link)
int
freebsd32_getcontext(struct thread *td, struct freebsd32_getcontext_args *uap)
{
struct ia32_ucontext uc;
int ret;
if (uap->ucp == NULL)
ret = EINVAL;
else {
ia32_get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
PROC_LOCK(td->td_proc);
uc.uc_sigmask = td->td_sigmask;
PROC_UNLOCK(td->td_proc);
ret = copyout(&uc, uap->ucp, UC_COPY_SIZE);
}
return (ret);
}
int
freebsd32_setcontext(struct thread *td, struct freebsd32_setcontext_args *uap)
{
struct ia32_ucontext uc;
int ret;
if (uap->ucp == NULL)
ret = EINVAL;
else {
ret = copyin(uap->ucp, &uc, UC_COPY_SIZE);
if (ret == 0) {
ret = ia32_set_mcontext(td, &uc.uc_mcontext);
if (ret == 0) {
SIG_CANTMASK(uc.uc_sigmask);
PROC_LOCK(td->td_proc);
td->td_sigmask = uc.uc_sigmask;
PROC_UNLOCK(td->td_proc);
}
}
}
return (ret == 0 ? EJUSTRETURN : ret);
}
int
freebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap)
{
struct ia32_ucontext uc;
int ret;
if (uap->oucp == NULL || uap->ucp == NULL)
ret = EINVAL;
else {
ia32_get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
PROC_LOCK(td->td_proc);
uc.uc_sigmask = td->td_sigmask;
PROC_UNLOCK(td->td_proc);
ret = copyout(&uc, uap->oucp, UC_COPY_SIZE);
if (ret == 0) {
ret = copyin(uap->ucp, &uc, UC_COPY_SIZE);
if (ret == 0) {
ret = ia32_set_mcontext(td, &uc.uc_mcontext);
if (ret == 0) {
SIG_CANTMASK(uc.uc_sigmask);
PROC_LOCK(td->td_proc);
td->td_sigmask = uc.uc_sigmask;
PROC_UNLOCK(td->td_proc);
}
}
}
}
return (ret == 0 ? EJUSTRETURN : ret);
}
/*
* Send an interrupt to process.
*

View File

@ -704,12 +704,13 @@
418 AUE_NULL UNIMPL __xstat
419 AUE_NULL UNIMPL __xfstat
420 AUE_NULL UNIMPL __xlstat
; XXX implement
421 AUE_NULL UNIMPL getcontext
; XXX implement
422 AUE_NULL UNIMPL setcontext
; XXX implement
423 AUE_NULL UNIMPL swapcontext
421 AUE_NULL STD { int freebsd32_getcontext( \
struct freebsd32_ucontext *ucp); }
422 AUE_NULL STD { int freebsd32_setcontext( \
const struct freebsd32_ucontext *ucp); }
423 AUE_NULL STD { int freebsd32_swapcontext( \
struct freebsd32_ucontext *oucp, \
const struct freebsd32_ucontext *ucp); }
424 AUE_SWAPOFF UNIMPL swapoff
425 AUE_NULL UNIMPL __acl_get_link
426 AUE_NULL UNIMPL __acl_set_link

View File

@ -247,3 +247,24 @@ ia32_savectx(struct pcb *pcb)
pcb->pcb_ia32_fir = ia64_get_fir();
pcb->pcb_ia32_fsr = ia64_get_fsr();
}
int
freebsd32_getcontext(struct thread *td, struct freebsd32_getcontext_args *uap)
{
return (nosys(td, NULL));
}
int
freebsd32_setcontext(struct thread *td, struct freebsd32_setcontext_args *uap)
{
return (nosys(td, NULL));
}
int
freebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap)
{
return (nosys(td, NULL));
}