Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 21 Jul 2005 23:25:01 GMT
From:      Peter Wemm <peter@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 80719 for review
Message-ID:  <200507212325.j6LNP1bQ031386@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=80719

Change 80719 by peter@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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200507212325.j6LNP1bQ031386>