17c478bdstevel@tonic-gate/*
27c478bdstevel@tonic-gate * CDDL HEADER START
37c478bdstevel@tonic-gate *
47c478bdstevel@tonic-gate * The contents of this file are subject to the terms of the
57c478bdstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bdstevel@tonic-gate * (the "License").  You may not use this file except in compliance
77c478bdstevel@tonic-gate * with the License.
87c478bdstevel@tonic-gate *
97c478bdstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bdstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bdstevel@tonic-gate * See the License for the specific language governing permissions
127c478bdstevel@tonic-gate * and limitations under the License.
137c478bdstevel@tonic-gate *
147c478bdstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bdstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bdstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bdstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bdstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bdstevel@tonic-gate *
207c478bdstevel@tonic-gate * CDDL HEADER END
217c478bdstevel@tonic-gate */
227c478bdstevel@tonic-gate/*
237c478bdstevel@tonic-gate * Copyright 1994-1998,2003 Sun Microsystems, Inc.  All rights reserved.
247c478bdstevel@tonic-gate * Use is subject to license terms.
257c478bdstevel@tonic-gate */
267c478bdstevel@tonic-gate
277c478bdstevel@tonic-gate#pragma ident	"%Z%%M%	%I%	%E% SMI"
287c478bdstevel@tonic-gate
297c478bdstevel@tonic-gate#include <sys/types.h>
307c478bdstevel@tonic-gate#include <sys/t_lock.h>
317c478bdstevel@tonic-gate#include <sys/klwp.h>
327c478bdstevel@tonic-gate#include <sys/ucontext.h>
337c478bdstevel@tonic-gate#include <sys/procfs.h>
347c478bdstevel@tonic-gate#include <sys/privregs.h>
357c478bdstevel@tonic-gate#include <sys/cpuvar.h>
367c478bdstevel@tonic-gate#include <sys/cmn_err.h>
377c478bdstevel@tonic-gate#include <sys/systm.h>
387c478bdstevel@tonic-gate#include <sys/archsystm.h>
397c478bdstevel@tonic-gate#include <sys/machsystm.h>
407c478bdstevel@tonic-gate#include <sys/fpu/fpusystm.h>
417c478bdstevel@tonic-gate
427c478bdstevel@tonic-gate/*
437c478bdstevel@tonic-gate * Association of extra register state with a struct ucontext is
447c478bdstevel@tonic-gate * done by placing an xrs_t within the uc_mcontext filler area.
457c478bdstevel@tonic-gate *
467c478bdstevel@tonic-gate * The following routines provide an interface for this association.
477c478bdstevel@tonic-gate */
487c478bdstevel@tonic-gate
497c478bdstevel@tonic-gate/*
507c478bdstevel@tonic-gate * clear the struct ucontext extra register state pointer
517c478bdstevel@tonic-gate */
527c478bdstevel@tonic-gate/* ARGSUSED */
537c478bdstevel@tonic-gatevoid
547c478bdstevel@tonic-gatexregs_clrptr(klwp_id_t lwp, ucontext_t *uc)
557c478bdstevel@tonic-gate{
567c478bdstevel@tonic-gate	uc->uc_mcontext.xrs.xrs_id = 0;
577c478bdstevel@tonic-gate	uc->uc_mcontext.xrs.xrs_ptr = NULL;
587c478bdstevel@tonic-gate}
597c478bdstevel@tonic-gate
607c478bdstevel@tonic-gate/*
617c478bdstevel@tonic-gate * indicate whether or not an extra register state
627c478bdstevel@tonic-gate * pointer is associated with a struct ucontext
637c478bdstevel@tonic-gate */
647c478bdstevel@tonic-gate/* ARGSUSED */
657c478bdstevel@tonic-gateint
667c478bdstevel@tonic-gatexregs_hasptr(klwp_id_t lwp, ucontext_t *uc)
677c478bdstevel@tonic-gate{
687c478bdstevel@tonic-gate	return (uc->uc_mcontext.xrs.xrs_id == XRS_ID);
697c478bdstevel@tonic-gate}
707c478bdstevel@tonic-gate
717c478bdstevel@tonic-gate/*
727c478bdstevel@tonic-gate * get the struct ucontext extra register state pointer field
737c478bdstevel@tonic-gate */
747c478bdstevel@tonic-gate/* ARGSUSED */
757c478bdstevel@tonic-gatecaddr_t
767c478bdstevel@tonic-gatexregs_getptr(klwp_id_t lwp, ucontext_t *uc)
777c478bdstevel@tonic-gate{
787c478bdstevel@tonic-gate	if (uc->uc_mcontext.xrs.xrs_id == XRS_ID)
797c478bdstevel@tonic-gate		return (uc->uc_mcontext.xrs.xrs_ptr);
807c478bdstevel@tonic-gate	return (NULL);
817c478bdstevel@tonic-gate}
827c478bdstevel@tonic-gate
837c478bdstevel@tonic-gate/*
847c478bdstevel@tonic-gate * set the struct ucontext extra register state pointer field
857c478bdstevel@tonic-gate */
867c478bdstevel@tonic-gate/* ARGSUSED */
877c478bdstevel@tonic-gatevoid
887c478bdstevel@tonic-gatexregs_setptr(klwp_id_t lwp, ucontext_t *uc, caddr_t xrp)
897c478bdstevel@tonic-gate{
907c478bdstevel@tonic-gate	uc->uc_mcontext.xrs.xrs_id = XRS_ID;
917c478bdstevel@tonic-gate	uc->uc_mcontext.xrs.xrs_ptr = xrp;
927c478bdstevel@tonic-gate}
937c478bdstevel@tonic-gate
947c478bdstevel@tonic-gate#ifdef _SYSCALL32_IMPL
957c478bdstevel@tonic-gate
967c478bdstevel@tonic-gate/* ARGSUSED */
977c478bdstevel@tonic-gatevoid
987c478bdstevel@tonic-gatexregs_clrptr32(klwp_id_t lwp, ucontext32_t *uc)
997c478bdstevel@tonic-gate{
1007c478bdstevel@tonic-gate	uc->uc_mcontext.xrs.xrs_id = 0;
1017c478bdstevel@tonic-gate	uc->uc_mcontext.xrs.xrs_ptr = 0;
1027c478bdstevel@tonic-gate}
1037c478bdstevel@tonic-gate
1047c478bdstevel@tonic-gate/* ARGSUSED */
1057c478bdstevel@tonic-gateint
1067c478bdstevel@tonic-gatexregs_hasptr32(klwp_id_t lwp, ucontext32_t *uc)
1077c478bdstevel@tonic-gate{
1087c478bdstevel@tonic-gate	return (uc->uc_mcontext.xrs.xrs_id == XRS_ID);
1097c478bdstevel@tonic-gate}
1107c478bdstevel@tonic-gate
1117c478bdstevel@tonic-gate/* ARGSUSED */
1127c478bdstevel@tonic-gatecaddr32_t
1137c478bdstevel@tonic-gatexregs_getptr32(klwp_id_t lwp, ucontext32_t *uc)
1147c478bdstevel@tonic-gate{
1157c478bdstevel@tonic-gate	if (uc->uc_mcontext.xrs.xrs_id == XRS_ID)
1167c478bdstevel@tonic-gate		return (uc->uc_mcontext.xrs.xrs_ptr);
1177c478bdstevel@tonic-gate	return (0);
1187c478bdstevel@tonic-gate}
1197c478bdstevel@tonic-gate
1207c478bdstevel@tonic-gate/* ARGSUSED */
1217c478bdstevel@tonic-gatevoid
1227c478bdstevel@tonic-gatexregs_setptr32(klwp_id_t lwp, ucontext32_t *uc, caddr32_t xrp)
1237c478bdstevel@tonic-gate{
1247c478bdstevel@tonic-gate	uc->uc_mcontext.xrs.xrs_id = XRS_ID;
1257c478bdstevel@tonic-gate	uc->uc_mcontext.xrs.xrs_ptr = xrp;
1267c478bdstevel@tonic-gate}
1277c478bdstevel@tonic-gate
1287c478bdstevel@tonic-gate#endif /* _SYSCALL32_IMPL */
1297c478bdstevel@tonic-gate
1307c478bdstevel@tonic-gate/*
1317c478bdstevel@tonic-gate * Extra register state manipulation routines.
1327c478bdstevel@tonic-gate * NOTE:  'lwp' might not correspond to 'curthread' in any of the
1337c478bdstevel@tonic-gate * functions below since they are called from code in /proc to get
1347c478bdstevel@tonic-gate * or set the extra registers of another lwp.
1357c478bdstevel@tonic-gate */
1367c478bdstevel@tonic-gate
1377c478bdstevel@tonic-gateint xregs_exists = 1;
1387c478bdstevel@tonic-gate
1397c478bdstevel@tonic-gate#define	GET_UPPER_32(all)		(uint32_t)((uint64_t)(all) >> 32)
1407c478bdstevel@tonic-gate#define	SET_ALL_64(upper, lower)	\
1417c478bdstevel@tonic-gate		(((uint64_t)(upper) << 32) | (uint32_t)(lower))
1427c478bdstevel@tonic-gate
1437c478bdstevel@tonic-gate
1447c478bdstevel@tonic-gate/*
1457c478bdstevel@tonic-gate * fill in the extra register state area specified with the
1467c478bdstevel@tonic-gate * specified lwp's non-floating-point extra register state
1477c478bdstevel@tonic-gate * information
1487c478bdstevel@tonic-gate */
1497c478bdstevel@tonic-gatevoid
1507c478bdstevel@tonic-gatexregs_getgregs(klwp_id_t lwp, caddr_t xrp)
1517c478bdstevel@tonic-gate{
1527c478bdstevel@tonic-gate	prxregset_t *xregs = (prxregset_t *)xrp;
1537c478bdstevel@tonic-gate	struct regs *rp = lwptoregs(lwp);
1547c478bdstevel@tonic-gate
1557c478bdstevel@tonic-gate	if (xregs == NULL)
1567c478bdstevel@tonic-gate		return;
1577c478bdstevel@tonic-gate
1587c478bdstevel@tonic-gate	xregs->pr_type = XR_TYPE_V8P;
1597c478bdstevel@tonic-gate
1607c478bdstevel@tonic-gate	xregs->pr_un.pr_v8p.pr_xg[XR_G0] = 0;
1617c478bdstevel@tonic-gate	xregs->pr_un.pr_v8p.pr_xg[XR_G1] = GET_UPPER_32(rp->r_g1);
1627c478bdstevel@tonic-gate	xregs->pr_un.pr_v8p.pr_xg[XR_G2] = GET_UPPER_32(rp->r_g2);
1637c478bdstevel@tonic-gate	xregs->pr_un.pr_v8p.pr_xg[XR_G3] = GET_UPPER_32(rp->r_g3);
1647c478bdstevel@tonic-gate	xregs->pr_un.pr_v8p.pr_xg[XR_G4] = GET_UPPER_32(rp->r_g4);
1657c478bdstevel@tonic-gate	xregs->pr_un.pr_v8p.pr_xg[XR_G5] = GET_UPPER_32(rp->r_g5);
1667c478bdstevel@tonic-gate	xregs->pr_un.pr_v8p.pr_xg[XR_G6] = GET_UPPER_32(rp->r_g6);
1677c478bdstevel@tonic-gate	xregs->pr_un.pr_v8p.pr_xg[XR_G7] = GET_UPPER_32(rp->r_g7);
1687c478bdstevel@tonic-gate
1697c478bdstevel@tonic-gate	xregs->pr_un.pr_v8p.pr_xo[XR_O0] = GET_UPPER_32(rp->r_o0);
1707c478bdstevel@tonic-gate	xregs->pr_un.pr_v8p.pr_xo[XR_O1] = GET_UPPER_32(rp->r_o1);
1717c478bdstevel@tonic-gate	xregs->pr_un.pr_v8p.pr_xo[XR_O2] = GET_UPPER_32(rp->r_o2);
1727c478bdstevel@tonic-gate	xregs->pr_un.pr_v8p.pr_xo[XR_O3] = GET_UPPER_32(rp->r_o3);
1737c478bdstevel@tonic-gate	xregs->pr_un.pr_v8p.pr_xo[XR_O4] = GET_UPPER_32(rp->r_o4);
1747c478bdstevel@tonic-gate	xregs->pr_un.pr_v8p.pr_xo[XR_O5] = GET_UPPER_32(rp->r_o5);
1757c478bdstevel@tonic-gate	xregs->pr_un.pr_v8p.pr_xo[XR_O6] = GET_UPPER_32(rp->r_o6);
1767c478bdstevel@tonic-gate	xregs->pr_un.pr_v8p.pr_xo[XR_O7] = GET_UPPER_32(rp->r_o7);
1777c478bdstevel@tonic-gate
1787c478bdstevel@tonic-gate	xregs->pr_un.pr_v8p.pr_tstate = rp->r_tstate;
1797c478bdstevel@tonic-gate
1807c478bdstevel@tonic-gate	xregs_getgfiller(lwp, xrp);
1817c478bdstevel@tonic-gate}
1827c478bdstevel@tonic-gate
1837c478bdstevel@tonic-gate/*
1847c478bdstevel@tonic-gate * fill in the extra register state area specified with the
1857c478bdstevel@tonic-gate * specified lwp's floating-point extra register state information
1867c478bdstevel@tonic-gate */
1877c478bdstevel@tonic-gatevoid
1887c478bdstevel@tonic-gatexregs_getfpregs(klwp_id_t lwp, caddr_t xrp)
1897c478bdstevel@tonic-gate{
1907c478bdstevel@tonic-gate	prxregset_t *xregs = (prxregset_t *)xrp;
1917c478bdstevel@tonic-gate	kfpu_t *fp = lwptofpu(lwp);
1927c478bdstevel@tonic-gate
1937c478bdstevel@tonic-gate	if (xregs == NULL)
1947c478bdstevel@tonic-gate		return;
1957c478bdstevel@tonic-gate
1967c478bdstevel@tonic-gate	kpreempt_disable();
1977c478bdstevel@tonic-gate
1987c478bdstevel@tonic-gate	xregs->pr_type = XR_TYPE_V8P;
1997c478bdstevel@tonic-gate
2007c478bdstevel@tonic-gate	if (ttolwp(curthread) == lwp)
2017c478bdstevel@tonic-gate		fp->fpu_fprs = _fp_read_fprs();
2027c478bdstevel@tonic-gate	if ((fp->fpu_en) || (fp->fpu_fprs & FPRS_FEF)) {
2037c478bdstevel@tonic-gate		/*
2047c478bdstevel@tonic-gate		 * If we have an fpu and the current thread owns the fp
2057c478bdstevel@tonic-gate		 * context, flush fp registers into the pcb.
2067c478bdstevel@tonic-gate		 */
2077c478bdstevel@tonic-gate		if (fpu_exists && (ttolwp(curthread) == lwp)) {
2087c478bdstevel@tonic-gate			if ((fp->fpu_fprs & FPRS_FEF) != FPRS_FEF) {
2097c478bdstevel@tonic-gate				uint32_t fprs = (FPRS_FEF|FPRS_DU|FPRS_DL);
2107c478bdstevel@tonic-gate
2117c478bdstevel@tonic-gate				_fp_write_fprs(fprs);
2127c478bdstevel@tonic-gate				fp->fpu_fprs = fprs;
2137c478bdstevel@tonic-gate#ifdef DEBUG
2147c478bdstevel@tonic-gate				if (fpdispr) {
2157c478bdstevel@tonic-gate					cmn_err(CE_NOTE, "xregs_getfpregs "
2167c478bdstevel@tonic-gate					    "with fp disabled!");
2177c478bdstevel@tonic-gate				}
2187c478bdstevel@tonic-gate#endif /* DEBUG */
2197c478bdstevel@tonic-gate			}
2207c478bdstevel@tonic-gate			fp_v8p_fksave(fp);
2217c478bdstevel@tonic-gate		}
2227c478bdstevel@tonic-gate		(void) kcopy(&fp->fpu_fr.fpu_dregs[16],
2237c478bdstevel@tonic-gate		    &xregs->pr_un.pr_v8p.pr_xfr,
2247c478bdstevel@tonic-gate		    sizeof (xregs->pr_un.pr_v8p.pr_xfr));
2257c478bdstevel@tonic-gate		xregs->pr_un.pr_v8p.pr_xfsr = GET_UPPER_32(fp->fpu_fsr);
2267c478bdstevel@tonic-gate		xregs->pr_un.pr_v8p.pr_fprs = fp->fpu_fprs;
2277c478bdstevel@tonic-gate
2287c478bdstevel@tonic-gate		xregs_getfpfiller(lwp, xrp);
2297c478bdstevel@tonic-gate	} else {
2307c478bdstevel@tonic-gate		int i;
2317c478bdstevel@tonic-gate		for (i = 0; i < 32; i++)			/* Nan */
2327c478bdstevel@tonic-gate			xregs->pr_un.pr_v8p.pr_xfr.pr_regs[i] = (uint32_t)-1;
2337c478bdstevel@tonic-gate	}
2347c478bdstevel@tonic-gate
2357c478bdstevel@tonic-gate	kpreempt_enable();
2367c478bdstevel@tonic-gate}
2377c478bdstevel@tonic-gate
2387c478bdstevel@tonic-gate/*
2397c478bdstevel@tonic-gate * fill in the extra register state area specified with
2407c478bdstevel@tonic-gate * the specified lwp's extra register state information
2417c478bdstevel@tonic-gate */
2427c478bdstevel@tonic-gatevoid
2437c478bdstevel@tonic-gatexregs_get(klwp_id_t lwp, caddr_t xrp)
2447c478bdstevel@tonic-gate{
2457c478bdstevel@tonic-gate	if (xrp != NULL) {
2467c478bdstevel@tonic-gate		bzero(xrp, sizeof (prxregset_t));
2477c478bdstevel@tonic-gate		xregs_getgregs(lwp, xrp);
2487c478bdstevel@tonic-gate		xregs_getfpregs(lwp, xrp);
2497c478bdstevel@tonic-gate	}
2507c478bdstevel@tonic-gate}
2517c478bdstevel@tonic-gate
2527c478bdstevel@tonic-gate/*
2537c478bdstevel@tonic-gate * set the specified lwp's non-floating-point extra
2547c478bdstevel@tonic-gate * register state based on the specified input
2557c478bdstevel@tonic-gate */
2567c478bdstevel@tonic-gatevoid
2577c478bdstevel@tonic-gatexregs_setgregs(klwp_id_t lwp, caddr_t xrp)
2587c478bdstevel@tonic-gate{
2597c478bdstevel@tonic-gate	prxregset_t *xregs = (prxregset_t *)xrp;
2607c478bdstevel@tonic-gate	struct regs *rp = lwptoregs(lwp);
2617c478bdstevel@tonic-gate	int current = (lwp == curthread->t_lwp);
2627c478bdstevel@tonic-gate
2637c478bdstevel@tonic-gate	if (xregs == NULL)
2647c478bdstevel@tonic-gate		return;
2657c478bdstevel@tonic-gate
2667c478bdstevel@tonic-gate#ifdef DEBUG
2677c478bdstevel@tonic-gate	if (xregs->pr_type != XR_TYPE_V8P) {
2687c478bdstevel@tonic-gate		cmn_err(CE_WARN,
2697c478bdstevel@tonic-gate		    "xregs_setgregs: pr_type is %d and should be %d",
2707c478bdstevel@tonic-gate		    xregs->pr_type, XR_TYPE_V8P);
2717c478bdstevel@tonic-gate	}
2727c478bdstevel@tonic-gate#endif /* DEBUG */
2737c478bdstevel@tonic-gate
2747c478bdstevel@tonic-gate	if (current) {
2757c478bdstevel@tonic-gate		/*
2767c478bdstevel@tonic-gate		 * copy the args from the regs first
2777c478bdstevel@tonic-gate		 */
2787c478bdstevel@tonic-gate		(void) save_syscall_args();
2797c478bdstevel@tonic-gate	}
2807c478bdstevel@tonic-gate
2817c478bdstevel@tonic-gate	rp->r_g1 = SET_ALL_64(xregs->pr_un.pr_v8p.pr_xg[XR_G1], rp->r_g1);
2827c478bdstevel@tonic-gate	rp->r_g2 = SET_ALL_64(xregs->pr_un.pr_v8p.pr_xg[XR_G2], rp->r_g2);
2837c478bdstevel@tonic-gate	rp->r_g3 = SET_ALL_64(xregs->pr_un.pr_v8p.pr_xg[XR_G3], rp->r_g3);
2847c478bdstevel@tonic-gate	rp->r_g4 = SET_ALL_64(xregs->pr_un.pr_v8p.pr_xg[XR_G4], rp->r_g4);
2857c478bdstevel@tonic-gate	rp->r_g5 = SET_ALL_64(xregs->pr_un.pr_v8p.pr_xg[XR_G5], rp->r_g5);
2867c478bdstevel@tonic-gate	rp->r_g6 = SET_ALL_64(xregs->pr_un.pr_v8p.pr_xg[XR_G6], rp->r_g6);
2877c478bdstevel@tonic-gate	rp->r_g7 = SET_ALL_64(xregs->pr_un.pr_v8p.pr_xg[XR_G7], rp->r_g7);
2887c478bdstevel@tonic-gate
2897c478bdstevel@tonic-gate	rp->r_o0 = SET_ALL_64(xregs->pr_un.pr_v8p.pr_xo[XR_O0], rp->r_o0);
2907c478bdstevel@tonic-gate	rp->r_o1 = SET_ALL_64(xregs->pr_un.pr_v8p.pr_xo[XR_O1], rp->r_o1);
2917c478bdstevel@tonic-gate	rp->r_o2 = SET_ALL_64(xregs->pr_un.pr_v8p.pr_xo[XR_O2], rp->r_o2);
2927c478bdstevel@tonic-gate	rp->r_o3 = SET_ALL_64(xregs->pr_un.pr_v8p.pr_xo[XR_O3], rp->r_o3);
2937c478bdstevel@tonic-gate	rp->r_o4 = SET_ALL_64(xregs->pr_un.pr_v8p.pr_xo[XR_O4], rp->r_o4);
2947c478bdstevel@tonic-gate	rp->r_o5 = SET_ALL_64(xregs->pr_un.pr_v8p.pr_xo[XR_O5], rp->r_o5);
2957c478bdstevel@tonic-gate	rp->r_o6 = SET_ALL_64(xregs->pr_un.pr_v8p.pr_xo[XR_O6], rp->r_o6);
2967c478bdstevel@tonic-gate	rp->r_o7 = SET_ALL_64(xregs->pr_un.pr_v8p.pr_xo[XR_O7], rp->r_o7);
2977c478bdstevel@tonic-gate
2987c478bdstevel@tonic-gate	rp->r_tstate &= ~((uint64_t)CCR_XCC << TSTATE_CCR_SHIFT);
2997c478bdstevel@tonic-gate	rp->r_tstate |= xregs->pr_un.pr_v8p.pr_tstate &
3007c478bdstevel@tonic-gate	    ((uint64_t)CCR_XCC << TSTATE_CCR_SHIFT);
3017c478bdstevel@tonic-gate	rp->r_tstate &= ~((uint64_t)TSTATE_ASI_MASK << TSTATE_ASI_SHIFT);
3027c478bdstevel@tonic-gate	rp->r_tstate |= xregs->pr_un.pr_v8p.pr_tstate &
3037c478bdstevel@tonic-gate	    ((uint64_t)TSTATE_ASI_MASK << TSTATE_ASI_SHIFT);
3047c478bdstevel@tonic-gate
3057c478bdstevel@tonic-gate	xregs_setgfiller(lwp, xrp);
3067c478bdstevel@tonic-gate
3077c478bdstevel@tonic-gate	if (current) {
3087c478bdstevel@tonic-gate		/*
3097c478bdstevel@tonic-gate		 * This was called from a system call, but we
3107c478bdstevel@tonic-gate		 * do not want to return via the shared window;
3117c478bdstevel@tonic-gate		 * restoring the CPU context changes everything.
3127c478bdstevel@tonic-gate		 */
3137c478bdstevel@tonic-gate		lwp->lwp_eosys = JUSTRETURN;
3147c478bdstevel@tonic-gate		curthread->t_post_sys = 1;
3157c478bdstevel@tonic-gate	}
3167c478bdstevel@tonic-gate}
3177c478bdstevel@tonic-gate
3187c478bdstevel@tonic-gate/*
3197c478bdstevel@tonic-gate * set the specified lwp's floating-point extra
3207c478bdstevel@tonic-gate * register state based on the specified input
3217c478bdstevel@tonic-gate */
3227c478bdstevel@tonic-gatevoid
3237c478bdstevel@tonic-gatexregs_setfpregs(klwp_id_t lwp, caddr_t xrp)
3247c478bdstevel@tonic-gate{
3257c478bdstevel@tonic-gate	prxregset_t *xregs = (prxregset_t *)xrp;
3267c478bdstevel@tonic-gate	kfpu_t *fp = lwptofpu(lwp);
3277c478bdstevel@tonic-gate
3287c478bdstevel@tonic-gate	if (xregs == NULL)
3297c478bdstevel@tonic-gate		return;
3307c478bdstevel@tonic-gate
3317c478bdstevel@tonic-gate#ifdef DEBUG
3327c478bdstevel@tonic-gate	if (xregs->pr_type != XR_TYPE_V8P) {
3337c478bdstevel@tonic-gate		cmn_err(CE_WARN,
3347c478bdstevel@tonic-gate		    "xregs_setfpregs: pr_type is %d and should be %d",
3357c478bdstevel@tonic-gate		    xregs->pr_type, XR_TYPE_V8P);
3367c478bdstevel@tonic-gate	}
3377c478bdstevel@tonic-gate#endif /* DEBUG */
3387c478bdstevel@tonic-gate	if ((fp->fpu_en) || (xregs->pr_un.pr_v8p.pr_fprs & FPRS_FEF)) {
3397c478bdstevel@tonic-gate		kpreempt_disable();
3407c478bdstevel@tonic-gate		(void) kcopy(&xregs->pr_un.pr_v8p.pr_xfr,
3417c478bdstevel@tonic-gate		    &fp->fpu_fr.fpu_dregs[16],
3427c478bdstevel@tonic-gate		    sizeof (xregs->pr_un.pr_v8p.pr_xfr));
3437c478bdstevel@tonic-gate		fp->fpu_fprs = xregs->pr_un.pr_v8p.pr_fprs;
3447c478bdstevel@tonic-gate		fp->fpu_fsr = SET_ALL_64(xregs->pr_un.pr_v8p.pr_xfsr,
3457c478bdstevel@tonic-gate		    fp->fpu_fsr);
3467c478bdstevel@tonic-gate
3477c478bdstevel@tonic-gate		xregs_setfpfiller(lwp, xrp);
3487c478bdstevel@tonic-gate
3497c478bdstevel@tonic-gate		/*
3507c478bdstevel@tonic-gate		 * If not the current lwp then resume() will handle it
3517c478bdstevel@tonic-gate		 */
3527c478bdstevel@tonic-gate		if (lwp != ttolwp(curthread)) {
3537c478bdstevel@tonic-gate			/* force resume to reload fp regs */
3547c478bdstevel@tonic-gate			kpreempt_enable();
3557c478bdstevel@tonic-gate			return;
3567c478bdstevel@tonic-gate		}
3577c478bdstevel@tonic-gate
3587c478bdstevel@tonic-gate		if (fpu_exists) {
3597c478bdstevel@tonic-gate			fp->fpu_fprs = _fp_read_fprs();
3607c478bdstevel@tonic-gate			if ((fp->fpu_fprs & FPRS_FEF) != FPRS_FEF) {
3617c478bdstevel@tonic-gate				uint32_t fprs = (FPRS_FEF|FPRS_DU|FPRS_DL);
3627c478bdstevel@tonic-gate
3637c478bdstevel@tonic-gate				_fp_write_fprs(fprs);
3647c478bdstevel@tonic-gate				fp->fpu_fprs = (V9_FPU_FPRS_TYPE)fprs;
3657c478bdstevel@tonic-gate#ifdef DEBUG
3667c478bdstevel@tonic-gate				if (fpdispr) {
3677c478bdstevel@tonic-gate					cmn_err(CE_NOTE, "xregs_setfpregs "
3687c478bdstevel@tonic-gate					    "with fp disabled!");
3697c478bdstevel@tonic-gate				}
3707c478bdstevel@tonic-gate#endif /* DEBUG */
3717c478bdstevel@tonic-gate			}
3727c478bdstevel@tonic-gate			fp_v8p_load(fp);
3737c478bdstevel@tonic-gate		}
3747c478bdstevel@tonic-gate
3757c478bdstevel@tonic-gate		kpreempt_enable();
3767c478bdstevel@tonic-gate	}
3777c478bdstevel@tonic-gate}
3787c478bdstevel@tonic-gate
3797c478bdstevel@tonic-gate/*
3807c478bdstevel@tonic-gate * set the specified lwp's extra register
3817c478bdstevel@tonic-gate * state based on the specified input
3827c478bdstevel@tonic-gate */
3837c478bdstevel@tonic-gatevoid
3847c478bdstevel@tonic-gatexregs_set(klwp_id_t lwp, caddr_t xrp)
3857c478bdstevel@tonic-gate{
3867c478bdstevel@tonic-gate	if (xrp != NULL) {
3877c478bdstevel@tonic-gate		xregs_setgregs(lwp, xrp);
3887c478bdstevel@tonic-gate		xregs_setfpregs(lwp, xrp);
3897c478bdstevel@tonic-gate	}
3907c478bdstevel@tonic-gate}
3917c478bdstevel@tonic-gate
3927c478bdstevel@tonic-gate/*
3937c478bdstevel@tonic-gate * return the size of the extra register state
3947c478bdstevel@tonic-gate */
3957c478bdstevel@tonic-gateint
3967c478bdstevel@tonic-gatexregs_getsize(proc_t *p)
3977c478bdstevel@tonic-gate{
3987c478bdstevel@tonic-gate	if (!xregs_exists || p->p_model == DATAMODEL_LP64)
3997c478bdstevel@tonic-gate		return (0);
4007c478bdstevel@tonic-gate	return (sizeof (prxregset_t));
4017c478bdstevel@tonic-gate}
402