--- /dev/null	2013-01-23 13:19:09.000000000 +0000
+++ new/usr/src/uts/intel/ia32/os/xregs.c	2013-01-23 13:19:09.297431276 +0000
@@ -0,0 +1,232 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 1994-1998,2003 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright 2013 David Hoeppner.  All rights reserved.
+ */
+
+#include <sys/types.h>
+#include <sys/t_lock.h>
+#include <sys/klwp.h>
+#include <sys/proc.h>
+#include <sys/ucontext.h>
+#include <sys/procfs.h>
+#include <sys/privregs.h>
+#include <sys/fp.h>
+#include <sys/cpuvar.h>
+#include <sys/cmn_err.h>
+#include <sys/disp.h>
+#include <sys/systm.h>
+#include <sys/archsystm.h>
+#include <sys/note.h>
+
+/*
+ * Clear the struct ucontext extra register state pointer.
+ */
+void
+xregs_clrptr(klwp_id_t lwp, ucontext_t *uc)
+{
+	uc->uc_xrs.xrs_id = 0;
+	uc->uc_xrs.xrs_ptr = NULL;
+}
+
+/*
+ * Indicate whether or not an extra register state
+ * pointer is associated with a struct ucontext.
+ */
+int
+xregs_hasptr(klwp_id_t lwp, ucontext_t *uc)
+{
+	_NOTE(ARGUNUSED(lwp));
+
+	return (uc->uc_xrs.xrs_id == XRS_ID);
+}
+
+/*
+ * Get the struct ucontext extra register state pointer field.
+ */
+caddr_t
+xregs_getptr(klwp_id_t lwp, ucontext_t *uc)
+{
+	_NOTE(ARGUNUSED(lwp));
+
+	if (uc->uc_xrs.xrs_id == XRS_ID)
+		return (uc->uc_xrs.xrs_ptr);
+
+	return (NULL);
+}
+
+/*
+ * Set the struct ucontext extra register state pointer field.
+ */
+void
+xregs_setptr(klwp_id_t lwp, ucontext_t *uc, caddr_t xrp)
+{
+	_NOTE(ARGUNUSED(lwp));
+
+	uc->uc_xrs.xrs_id = XRS_ID;
+	uc->uc_xrs.xrs_ptr = xrp;
+}
+
+#if defined(_SYSCALL32_IMPL)
+
+void
+xregs_clrptr32(klwp_id_t lwp, ucontext32_t *uc)
+{
+	_NOTE(ARGUNUSED(lwp));
+
+	uc->uc_xrs.xrs_id = 0;
+	uc->uc_xrs.xrs_ptr = NULL;
+}
+
+int
+xregs_hasptr32(klwp_id_t lwp, ucontext32_t *uc)
+{
+	_NOTE(ARGUNUSED(lwp));
+
+	return (uc->uc_xrs.xrs_id == XRS_ID);
+}
+
+caddr32_t
+xregs_getptr32(klwp_id_t lwp, ucontext32_t *uc)
+{
+	_NOTE(ARGUNUSED(lwp));
+
+	if (uc->uc_xrs.xrs_id == XRS_ID)
+		return (uc->uc_xrs.xrs_ptr);
+
+	return (0);
+}
+
+void
+xregs_setptr32(klwp_id_t lwp, ucontext32_t *uc, caddr32_t xrp)
+{
+	_NOTE(ARGUNUSED(lwp));
+
+	uc->uc_xrs.xrs_id = XRS_ID;
+	uc->uc_xrs.xrs_ptr = xrp;
+}
+
+#endif	/* _SYSCALL32_IMPL */
+
+/*
+ * Fill in the extra register state area specified with the
+ * specified lwp's floating point extra register state information.
+ */
+void
+xregs_getfpregs(klwp_id_t lwp, caddr_t xrp)
+{
+	prxregset_t *xregs = (prxregset_t *)xrp;
+	kfpu_t *fp = lwptofpu(lwp);
+
+	if (xregs == NULL)
+		return;
+
+	kpreempt_disable();
+
+	xregs->pr_type = XR_TYPE_XSAVE;
+
+	kpreempt_enable();
+}
+
+/*
+ * Fill in the extra register state area specified with
+ * the specified kwp's extra register state information.
+ */
+void
+xregs_get(klwp_id_t lwp, caddr_t xrp)
+{
+
+	if (xrp != NULL) {
+		bzero(xrp, sizeof (prxregset_t));
+		xregs_getfpregs(lwp, xrp);
+	}
+}
+
+/*
+ * Set the specified lwp's floating-point extra
+ * register state based on the specified input.
+ */
+void
+xregs_setfpregs(klwp_id_t lwp, caddr_t xrp)
+{
+	prxregset_t *xregs = (prxregset_t *)xrp;
+	kfpu_t *fp = lwptofpu(lwp);
+	fpu_ctx_t *fpu = &lwp->lwp_pcb.pcb_fpu;
+
+	if (xregs == NULL)
+		return;
+
+#if defined(DEBUG)
+	if (xregs->pr_type != XR_TYPE_XSAVE) {
+		cmn_err(CE_WARN,
+		    "xregs_setfpregs: pr_type is %d and should be %d",
+		    xregs->pr_type, XR_TYPE_XSAVE);
+	}
+#endif	/* DEBUG */
+
+	if (fpu->fpu_flags & FPU_EN) {
+		kpreempt_disable();
+		(void) kcopy(&xregs->pr_un.pr_xsave.pr_ymm,
+		    &fp->kfpu_u.kfpu_xs.xs_ymm,
+		    sizeof (&xregs->pr_un.pr_xsave.pr_ymm));
+
+		/*
+		 * If not the current lwp then resume() will handle it.
+		 */
+		if (lwp != ttolwp(curthread)) {
+			/* Force resume to reload fp regs */
+			kpreempt_enable();
+			return;
+		}
+
+		if (fpu_exists) {
+		}
+
+		kpreempt_enable();
+	}
+}
+
+/*
+ * Set the specified lwp's extra register
+ * state based on the specified input.
+ */
+void
+xregs_set(klwp_id_t lwp, caddr_t xrp)
+{
+	if (xrp != NULL) {
+		xregs_setfpregs(lwp, xrp);
+	}
+}
+
+/*
+ * Return the size of the extra register state.
+ */
+int
+xregs_getsize(proc_t *p)
+{
+	return (sizeof (prxregset_t));
+}
