PERFORCE change 80719 for review
Peter Wemm
peter at FreeBSD.org
Thu Jul 21 23:25:04 GMT 2005
http://perforce.freebsd.org/chv.cgi?CH=80719
Change 80719 by peter at peter_daintree on 2005/07/21 23:24:36
implement getcontext/setcontext/swapcontext(2) wrappers
Affected files ...
.. //depot/projects/hammer/sys/amd64/ia32/ia32_signal.c#14 edit
.. //depot/projects/hammer/sys/compat/freebsd32/freebsd32_proto.h#31 edit
.. //depot/projects/hammer/sys/compat/freebsd32/freebsd32_syscall.h#29 edit
.. //depot/projects/hammer/sys/compat/freebsd32/freebsd32_syscalls.c#29 edit
.. //depot/projects/hammer/sys/compat/freebsd32/freebsd32_sysent.c#29 edit
.. //depot/projects/hammer/sys/compat/freebsd32/syscalls.master#33 edit
Differences ...
==== //depot/projects/hammer/sys/amd64/ia32/ia32_signal.c#14 (text+ko) ====
@@ -92,38 +92,14 @@
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
- * fpugetregs()'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 = fpugetregs(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_ownedfp = fpugetregs(td, (struct savefpu *)&mcp->mc_fpstate);
mcp->mc_fpformat = fpuformat();
}
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);
@@ -134,31 +110,180 @@
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 fpusetregs()
* be called with interrupts disabled.
*/
- fpusetregs(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.
- */
+ fpusetregs(td, (struct savefpu *)&mcp->mc_fpstate);
} else
return (EINVAL);
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.
*
* Stack is set up to allow sigcode stored
==== //depot/projects/hammer/sys/compat/freebsd32/freebsd32_proto.h#31 (text+ko) ====
@@ -2,7 +2,7 @@
* System call prototypes.
*
* DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/compat/freebsd32/freebsd32_proto.h,v 1.39 2005/07/13 20:35:08 jhb Exp $
+ * $FreeBSD$
* created from FreeBSD: src/sys/compat/freebsd32/syscalls.master,v 1.51 2005/07/13 20:32:42 jhb Exp
*/
@@ -225,6 +225,16 @@
struct freebsd32_sigreturn_args {
char sigcntxp_l_[PADL_(const struct freebsd32_ucontext *)]; const struct freebsd32_ucontext * sigcntxp; char sigcntxp_r_[PADR_(const struct freebsd32_ucontext *)];
};
+struct freebsd32_getcontext_args {
+ char ucp_l_[PADL_(struct freebsd32_ucontext *)]; struct freebsd32_ucontext * ucp; char ucp_r_[PADR_(struct freebsd32_ucontext *)];
+};
+struct freebsd32_setcontext_args {
+ char ucp_l_[PADL_(const struct freebsd32_ucontext *)]; const struct freebsd32_ucontext * ucp; char ucp_r_[PADR_(const struct freebsd32_ucontext *)];
+};
+struct freebsd32_swapcontext_args {
+ char oucp_l_[PADL_(struct freebsd32_ucontext *)]; struct freebsd32_ucontext * oucp; char oucp_r_[PADR_(struct freebsd32_ucontext *)];
+ char ucp_l_[PADL_(const struct freebsd32_ucontext *)]; const struct freebsd32_ucontext * ucp; char ucp_r_[PADR_(const struct freebsd32_ucontext *)];
+};
int freebsd32_wait4(struct thread *, struct freebsd32_wait4_args *);
int freebsd32_sigaltstack(struct thread *, struct freebsd32_sigaltstack_args *);
int freebsd32_execve(struct thread *, struct freebsd32_execve_args *);
@@ -259,6 +269,9 @@
int freebsd32_sendfile(struct thread *, struct freebsd32_sendfile_args *);
int freebsd32_sigaction(struct thread *, struct freebsd32_sigaction_args *);
int freebsd32_sigreturn(struct thread *, struct freebsd32_sigreturn_args *);
+int freebsd32_getcontext(struct thread *, struct freebsd32_getcontext_args *);
+int freebsd32_setcontext(struct thread *, struct freebsd32_setcontext_args *);
+int freebsd32_swapcontext(struct thread *, struct freebsd32_swapcontext_args *);
#ifdef COMPAT_43
==== //depot/projects/hammer/sys/compat/freebsd32/freebsd32_syscall.h#29 (text+ko) ====
@@ -2,7 +2,7 @@
* System call numbers.
*
* DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/compat/freebsd32/freebsd32_syscall.h,v 1.39 2005/07/13 20:35:08 jhb Exp $
+ * $FreeBSD$
* created from FreeBSD: src/sys/compat/freebsd32/syscalls.master,v 1.51 2005/07/13 20:32:42 jhb Exp
*/
@@ -294,6 +294,9 @@
#define FREEBSD32_SYS_fhstatfs 398
#define FREEBSD32_SYS_freebsd32_sigaction 416
#define FREEBSD32_SYS_freebsd32_sigreturn 417
+#define FREEBSD32_SYS_freebsd32_getcontext 421
+#define FREEBSD32_SYS_freebsd32_setcontext 422
+#define FREEBSD32_SYS_freebsd32_swapcontext 423
#define FREEBSD32_SYS_thr_create 430
#define FREEBSD32_SYS_thr_exit 431
#define FREEBSD32_SYS_thr_self 432
==== //depot/projects/hammer/sys/compat/freebsd32/freebsd32_syscalls.c#29 (text+ko) ====
@@ -2,7 +2,7 @@
* System call names.
*
* DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/compat/freebsd32/freebsd32_syscalls.c,v 1.30 2005/07/13 20:35:08 jhb Exp $
+ * $FreeBSD$
* created from FreeBSD: src/sys/compat/freebsd32/syscalls.master,v 1.51 2005/07/13 20:32:42 jhb Exp
*/
@@ -428,9 +428,9 @@
"#418", /* 418 = __xstat */
"#419", /* 419 = __xfstat */
"#420", /* 420 = __xlstat */
- "#421", /* 421 = getcontext */
- "#422", /* 422 = setcontext */
- "#423", /* 423 = swapcontext */
+ "freebsd32_getcontext", /* 421 = freebsd32_getcontext */
+ "freebsd32_setcontext", /* 422 = freebsd32_setcontext */
+ "freebsd32_swapcontext", /* 423 = freebsd32_swapcontext */
"#424", /* 424 = swapoff */
"#425", /* 425 = __acl_get_link */
"#426", /* 426 = __acl_set_link */
==== //depot/projects/hammer/sys/compat/freebsd32/freebsd32_sysent.c#29 (text+ko) ====
@@ -2,7 +2,7 @@
* System call switch table.
*
* DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/compat/freebsd32/freebsd32_sysent.c,v 1.40 2005/07/13 20:35:08 jhb Exp $
+ * $FreeBSD$
* created from FreeBSD: src/sys/compat/freebsd32/syscalls.master,v 1.51 2005/07/13 20:32:42 jhb Exp
*/
@@ -447,9 +447,9 @@
{ 0, (sy_call_t *)nosys, AUE_NULL }, /* 418 = __xstat */
{ 0, (sy_call_t *)nosys, AUE_NULL }, /* 419 = __xfstat */
{ 0, (sy_call_t *)nosys, AUE_NULL }, /* 420 = __xlstat */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 421 = getcontext */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 422 = setcontext */
- { 0, (sy_call_t *)nosys, AUE_NULL }, /* 423 = swapcontext */
+ { SYF_MPSAFE | AS(freebsd32_getcontext_args), (sy_call_t *)freebsd32_getcontext, AUE_NULL }, /* 421 = freebsd32_getcontext */
+ { SYF_MPSAFE | AS(freebsd32_setcontext_args), (sy_call_t *)freebsd32_setcontext, AUE_NULL }, /* 422 = freebsd32_setcontext */
+ { SYF_MPSAFE | AS(freebsd32_swapcontext_args), (sy_call_t *)freebsd32_swapcontext, AUE_NULL }, /* 423 = freebsd32_swapcontext */
{ 0, (sy_call_t *)nosys, AUE_NULL }, /* 424 = swapoff */
{ 0, (sy_call_t *)nosys, AUE_NULL }, /* 425 = __acl_get_link */
{ 0, (sy_call_t *)nosys, AUE_NULL }, /* 426 = __acl_set_link */
==== //depot/projects/hammer/sys/compat/freebsd32/syscalls.master#33 (text+ko) ====
@@ -693,12 +693,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 MSTD { int freebsd32_getcontext( \
+ struct freebsd32_ucontext *ucp); }
+422 AUE_NULL MSTD { int freebsd32_setcontext( \
+ const struct freebsd32_ucontext *ucp); }
+423 AUE_NULL MSTD { int freebsd32_swapcontext( \
+ struct freebsd32_ucontext *oucp, \
+ const struct freebsd32_ucontext *ucp); }
424 AUE_NULL UNIMPL swapoff
425 AUE_NULL UNIMPL __acl_get_link
426 AUE_NULL UNIMPL __acl_set_link
More information about the p4-projects
mailing list