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
58548bf7nr * Common Development and Distribution License (the "License").
68548bf7nr * You may not use this file except in compliance with the License.
77c478bdstevel@tonic-gate *
87c478bdstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bdstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bdstevel@tonic-gate * See the License for the specific language governing permissions
117c478bdstevel@tonic-gate * and limitations under the License.
127c478bdstevel@tonic-gate *
137c478bdstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bdstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bdstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bdstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bdstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bdstevel@tonic-gate *
197c478bdstevel@tonic-gate * CDDL HEADER END
207c478bdstevel@tonic-gate */
217552190raf
227c478bdstevel@tonic-gate/*
232c5124aPrashanth Sreenivasa * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
247c478bdstevel@tonic-gate * Use is subject to license terms.
257c478bdstevel@tonic-gate */
267c478bdstevel@tonic-gate
277c478bdstevel@tonic-gate/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
281255103Toomas Soome/*	  All Rights Reserved	*/
297c478bdstevel@tonic-gate
307c478bdstevel@tonic-gate#include <sys/types.h>
317c478bdstevel@tonic-gate#include <sys/t_lock.h>
327c478bdstevel@tonic-gate#include <sys/param.h>
337c478bdstevel@tonic-gate#include <sys/cred.h>
347c478bdstevel@tonic-gate#include <sys/debug.h>
357c478bdstevel@tonic-gate#include <sys/inline.h>
367c478bdstevel@tonic-gate#include <sys/kmem.h>
377c478bdstevel@tonic-gate#include <sys/proc.h>
387c478bdstevel@tonic-gate#include <sys/sysmacros.h>
397c478bdstevel@tonic-gate#include <sys/systm.h>
407c478bdstevel@tonic-gate#include <sys/vmsystm.h>
417c478bdstevel@tonic-gate#include <sys/vfs.h>
427c478bdstevel@tonic-gate#include <sys/vnode.h>
437c478bdstevel@tonic-gate#include <sys/pcb.h>
447c478bdstevel@tonic-gate#include <sys/buf.h>
457c478bdstevel@tonic-gate#include <sys/signal.h>
467c478bdstevel@tonic-gate#include <sys/user.h>
477c478bdstevel@tonic-gate#include <sys/cpuvar.h>
487c478bdstevel@tonic-gate#include <sys/copyops.h>
497c478bdstevel@tonic-gate#include <sys/watchpoint.h>
507c478bdstevel@tonic-gate
517c478bdstevel@tonic-gate#include <sys/fault.h>
527c478bdstevel@tonic-gate#include <sys/syscall.h>
537c478bdstevel@tonic-gate#include <sys/procfs.h>
547c478bdstevel@tonic-gate#include <sys/archsystm.h>
557c478bdstevel@tonic-gate#include <sys/cmn_err.h>
567c478bdstevel@tonic-gate#include <sys/stack.h>
577c478bdstevel@tonic-gate#include <sys/machpcb.h>
587c478bdstevel@tonic-gate#include <sys/simulate.h>
597c478bdstevel@tonic-gate#include <sys/fpu/fpusystm.h>
607c478bdstevel@tonic-gate
617c478bdstevel@tonic-gate#include <sys/pte.h>
627c478bdstevel@tonic-gate#include <sys/vmem.h>
637c478bdstevel@tonic-gate#include <sys/mman.h>
647c478bdstevel@tonic-gate#include <sys/vmparam.h>
657c478bdstevel@tonic-gate#include <vm/hat.h>
667c478bdstevel@tonic-gate#include <vm/as.h>
677c478bdstevel@tonic-gate#include <vm/seg.h>
687c478bdstevel@tonic-gate#include <vm/seg_kmem.h>
697c478bdstevel@tonic-gate#include <vm/seg_kp.h>
707c478bdstevel@tonic-gate#include <vm/page.h>
717c478bdstevel@tonic-gate
727c478bdstevel@tonic-gate#include <fs/proc/prdata.h>
737c478bdstevel@tonic-gate#include <v9/sys/psr_compat.h>
747c478bdstevel@tonic-gate
757c478bdstevel@tonic-gateint	prnwatch = 10000;	/* maximum number of watched areas */
767c478bdstevel@tonic-gate
777c478bdstevel@tonic-gate/*
787c478bdstevel@tonic-gate * Force a thread into the kernel if it is not already there.
797c478bdstevel@tonic-gate * This is a no-op on uniprocessors.
807c478bdstevel@tonic-gate */
817c478bdstevel@tonic-gate/* ARGSUSED */
827c478bdstevel@tonic-gatevoid
837c478bdstevel@tonic-gateprpokethread(kthread_t *t)
847c478bdstevel@tonic-gate{
857c478bdstevel@tonic-gate	if (t->t_state == TS_ONPROC && t->t_cpu != CPU)
867c478bdstevel@tonic-gate		poke_cpu(t->t_cpu->cpu_id);
877c478bdstevel@tonic-gate}
887c478bdstevel@tonic-gate
897c478bdstevel@tonic-gate/*
907c478bdstevel@tonic-gate * Return general registers.
917c478bdstevel@tonic-gate */
927c478bdstevel@tonic-gatevoid
937c478bdstevel@tonic-gateprgetprregs(klwp_t *lwp, prgregset_t prp)
947c478bdstevel@tonic-gate{
957c478bdstevel@tonic-gate	gregset_t gr;
967c478bdstevel@tonic-gate
977c478bdstevel@tonic-gate	ASSERT(MUTEX_NOT_HELD(&lwptoproc(lwp)->p_lock));
987c478bdstevel@tonic-gate
997c478bdstevel@tonic-gate	getgregs(lwp, gr);
1004cf53d5Toomas Soome	bzero(prp, NPRGREG * sizeof (*prp));
1017c478bdstevel@tonic-gate
1027c478bdstevel@tonic-gate	/*
1037c478bdstevel@tonic-gate	 * Can't copy since prgregset_t and gregset_t
1047c478bdstevel@tonic-gate	 * use different defines.
1057c478bdstevel@tonic-gate	 */
1067c478bdstevel@tonic-gate	prp[R_G1] = gr[REG_G1];
1077c478bdstevel@tonic-gate	prp[R_G2] = gr[REG_G2];
1087c478bdstevel@tonic-gate	prp[R_G3] = gr[REG_G3];
1097c478bdstevel@tonic-gate	prp[R_G4] = gr[REG_G4];
1107c478bdstevel@tonic-gate	prp[R_G5] = gr[REG_G5];
1117c478bdstevel@tonic-gate	prp[R_G6] = gr[REG_G6];
1127c478bdstevel@tonic-gate	prp[R_G7] = gr[REG_G7];
1137c478bdstevel@tonic-gate
1147c478bdstevel@tonic-gate	prp[R_O0] = gr[REG_O0];
1157c478bdstevel@tonic-gate	prp[R_O1] = gr[REG_O1];
1167c478bdstevel@tonic-gate	prp[R_O2] = gr[REG_O2];
1177c478bdstevel@tonic-gate	prp[R_O3] = gr[REG_O3];
1187c478bdstevel@tonic-gate	prp[R_O4] = gr[REG_O4];
1197c478bdstevel@tonic-gate	prp[R_O5] = gr[REG_O5];
1207c478bdstevel@tonic-gate	prp[R_O6] = gr[REG_O6];
1217c478bdstevel@tonic-gate	prp[R_O7] = gr[REG_O7];
1227c478bdstevel@tonic-gate
1237c478bdstevel@tonic-gate	if (lwp->lwp_pcb.pcb_xregstat != XREGNONE) {
1247c478bdstevel@tonic-gate		prp[R_L0] = lwp->lwp_pcb.pcb_xregs.rw_local[0];
1257c478bdstevel@tonic-gate		prp[R_L1] = lwp->lwp_pcb.pcb_xregs.rw_local[1];
1267c478bdstevel@tonic-gate		prp[R_L2] = lwp->lwp_pcb.pcb_xregs.rw_local[2];
1277c478bdstevel@tonic-gate		prp[R_L3] = lwp->lwp_pcb.pcb_xregs.rw_local[3];
1287c478bdstevel@tonic-gate		prp[R_L4] = lwp->lwp_pcb.pcb_xregs.rw_local[4];
1297c478bdstevel@tonic-gate		prp[R_L5] = lwp->lwp_pcb.pcb_xregs.rw_local[5];
1307c478bdstevel@tonic-gate		prp[R_L6] = lwp->lwp_pcb.pcb_xregs.rw_local[6];
1317c478bdstevel@tonic-gate		prp[R_L7] = lwp->lwp_pcb.pcb_xregs.rw_local[7];
1327c478bdstevel@tonic-gate
1337c478bdstevel@tonic-gate		prp[R_I0] = lwp->lwp_pcb.pcb_xregs.rw_in[0];
1347c478bdstevel@tonic-gate		prp[R_I1] = lwp->lwp_pcb.pcb_xregs.rw_in[1];
1357c478bdstevel@tonic-gate		prp[R_I2] = lwp->lwp_pcb.pcb_xregs.rw_in[2];
1367c478bdstevel@tonic-gate		prp[R_I3] = lwp->lwp_pcb.pcb_xregs.rw_in[3];
1377c478bdstevel@tonic-gate		prp[R_I4] = lwp->lwp_pcb.pcb_xregs.rw_in[4];
1387c478bdstevel@tonic-gate		prp[R_I5] = lwp->lwp_pcb.pcb_xregs.rw_in[5];
1397c478bdstevel@tonic-gate		prp[R_I6] = lwp->lwp_pcb.pcb_xregs.rw_in[6];
1407c478bdstevel@tonic-gate		prp[R_I7] = lwp->lwp_pcb.pcb_xregs.rw_in[7];
1417c478bdstevel@tonic-gate	}
1427c478bdstevel@tonic-gate
1437c478bdstevel@tonic-gate	prp[R_CCR] = gr[REG_CCR];
1447c478bdstevel@tonic-gate	prp[R_ASI] = gr[REG_ASI];
1457c478bdstevel@tonic-gate	prp[R_FPRS] = gr[REG_FPRS];
1467c478bdstevel@tonic-gate	prp[R_PC]  = gr[REG_PC];
1477c478bdstevel@tonic-gate	prp[R_nPC] = gr[REG_nPC];
1487c478bdstevel@tonic-gate	prp[R_Y]   = gr[REG_Y];
1497c478bdstevel@tonic-gate}
1507c478bdstevel@tonic-gate
1517c478bdstevel@tonic-gate/*
1527c478bdstevel@tonic-gate * Set general registers.
1537c478bdstevel@tonic-gate */
1547c478bdstevel@tonic-gatevoid
1557c478bdstevel@tonic-gateprsetprregs(klwp_t *lwp, prgregset_t prp, int initial)
1567c478bdstevel@tonic-gate{
1577c478bdstevel@tonic-gate	gregset_t gr;
1587c478bdstevel@tonic-gate
1597c478bdstevel@tonic-gate	gr[REG_G1] = prp[R_G1];
1607c478bdstevel@tonic-gate	gr[REG_G2] = prp[R_G2];
1617c478bdstevel@tonic-gate	gr[REG_G3] = prp[R_G3];
1627c478bdstevel@tonic-gate	gr[REG_G4] = prp[R_G4];
1637c478bdstevel@tonic-gate	gr[REG_G5] = prp[R_G5];
1647c478bdstevel@tonic-gate	gr[REG_G6] = prp[R_G6];
1657c478bdstevel@tonic-gate	gr[REG_G7] = prp[R_G7];
1667c478bdstevel@tonic-gate
1677c478bdstevel@tonic-gate	gr[REG_O0] = prp[R_O0];
1687c478bdstevel@tonic-gate	gr[REG_O1] = prp[R_O1];
1697c478bdstevel@tonic-gate	gr[REG_O2] = prp[R_O2];
1707c478bdstevel@tonic-gate	gr[REG_O3] = prp[R_O3];
1717c478bdstevel@tonic-gate	gr[REG_O4] = prp[R_O4];
1727c478bdstevel@tonic-gate	gr[REG_O5] = prp[R_O5];
1737c478bdstevel@tonic-gate	gr[REG_O6] = prp[R_O6];
1747c478bdstevel@tonic-gate	gr[REG_O7] = prp[R_O7];
1757c478bdstevel@tonic-gate
1767c478bdstevel@tonic-gate	lwp->lwp_pcb.pcb_xregs.rw_local[0] = prp[R_L0];
1777c478bdstevel@tonic-gate	lwp->lwp_pcb.pcb_xregs.rw_local[1] = prp[R_L1];
1787c478bdstevel@tonic-gate	lwp->lwp_pcb.pcb_xregs.rw_local[2] = prp[R_L2];
1797c478bdstevel@tonic-gate	lwp->lwp_pcb.pcb_xregs.rw_local[3] = prp[R_L3];
1807c478bdstevel@tonic-gate	lwp->lwp_pcb.pcb_xregs.rw_local[4] = prp[R_L4];
1817c478bdstevel@tonic-gate	lwp->lwp_pcb.pcb_xregs.rw_local[5] = prp[R_L5];
1827c478bdstevel@tonic-gate	lwp->lwp_pcb.pcb_xregs.rw_local[6] = prp[R_L6];
1837c478bdstevel@tonic-gate	lwp->lwp_pcb.pcb_xregs.rw_local[7] = prp[R_L7];
1847c478bdstevel@tonic-gate
1857c478bdstevel@tonic-gate	lwp->lwp_pcb.pcb_xregs.rw_in[0] = prp[R_I0];
1867c478bdstevel@tonic-gate	lwp->lwp_pcb.pcb_xregs.rw_in[1] = prp[R_I1];
1877c478bdstevel@tonic-gate	lwp->lwp_pcb.pcb_xregs.rw_in[2] = prp[R_I2];
1887c478bdstevel@tonic-gate	lwp->lwp_pcb.pcb_xregs.rw_in[3] = prp[R_I3];
1897c478bdstevel@tonic-gate	lwp->lwp_pcb.pcb_xregs.rw_in[4] = prp[R_I4];
1907c478bdstevel@tonic-gate	lwp->lwp_pcb.pcb_xregs.rw_in[5] = prp[R_I5];
1917c478bdstevel@tonic-gate	lwp->lwp_pcb.pcb_xregs.rw_in[6] = prp[R_I6];
1927c478bdstevel@tonic-gate	lwp->lwp_pcb.pcb_xregs.rw_in[7] = prp[R_I7];
1937c478bdstevel@tonic-gate
1947c478bdstevel@tonic-gate	lwp->lwp_pcb.pcb_xregstat = XREGMODIFIED;
1957c478bdstevel@tonic-gate	lwptot(lwp)->t_post_sys = 1;
1967c478bdstevel@tonic-gate
1977c478bdstevel@tonic-gate	/*
1987c478bdstevel@tonic-gate	 * setgregs will only allow the condition codes to be set.
1997c478bdstevel@tonic-gate	 */
2007c478bdstevel@tonic-gate	gr[REG_CCR] = prp[R_CCR];
2017c478bdstevel@tonic-gate	gr[REG_ASI] = prp[R_ASI];
2027c478bdstevel@tonic-gate	gr[REG_FPRS] = prp[R_FPRS];
2037c478bdstevel@tonic-gate	gr[REG_PC]  = prp[R_PC];
2047c478bdstevel@tonic-gate	gr[REG_nPC] = prp[R_nPC];
2057c478bdstevel@tonic-gate	gr[REG_Y]   = prp[R_Y];
2067c478bdstevel@tonic-gate
2077c478bdstevel@tonic-gate	if (initial) {		/* set initial values */
2087c478bdstevel@tonic-gate		if (lwptoproc(lwp)->p_model == DATAMODEL_LP64)
2092c5124aPrashanth Sreenivasa			lwptoregs(lwp)->r_tstate = TSTATE_USER64|TSTATE_MM_TSO;
2107c478bdstevel@tonic-gate		else
2112c5124aPrashanth Sreenivasa			lwptoregs(lwp)->r_tstate = TSTATE_USER32|TSTATE_MM_TSO;
2127c478bdstevel@tonic-gate		if (!fpu_exists)
2137c478bdstevel@tonic-gate			lwptoregs(lwp)->r_tstate &= ~TSTATE_PEF;
2147c478bdstevel@tonic-gate	}
2157c478bdstevel@tonic-gate
2167c478bdstevel@tonic-gate	setgregs(lwp, gr);
2177c478bdstevel@tonic-gate}
2187c478bdstevel@tonic-gate
2197c478bdstevel@tonic-gate#ifdef _SYSCALL32_IMPL
2207c478bdstevel@tonic-gate
2217c478bdstevel@tonic-gate/*
2227c478bdstevel@tonic-gate * modify the lower 32bits of a uint64_t
2237c478bdstevel@tonic-gate */
2247c478bdstevel@tonic-gate#define	SET_LOWER_32(all, lower)	\
2257c478bdstevel@tonic-gate	(((uint64_t)(all) & 0xffffffff00000000) | (uint32_t)(lower))
2267c478bdstevel@tonic-gate
2277c478bdstevel@tonic-gate/*
2287c478bdstevel@tonic-gate * Convert prgregset32 to native prgregset.
2297c478bdstevel@tonic-gate */
2307c478bdstevel@tonic-gatevoid
2317c478bdstevel@tonic-gateprgregset_32ton(klwp_t *lwp, prgregset32_t src, prgregset_t dest)
2327c478bdstevel@tonic-gate{
2337c478bdstevel@tonic-gate	struct regs *r = lwptoregs(lwp);
2347c478bdstevel@tonic-gate
2357c478bdstevel@tonic-gate	dest[R_G0] = SET_LOWER_32(0, src[R_G0]);
2367c478bdstevel@tonic-gate	dest[R_G1] = SET_LOWER_32(r->r_g1, src[R_G1]);
2377c478bdstevel@tonic-gate	dest[R_G2] = SET_LOWER_32(r->r_g2, src[R_G2]);
2387c478bdstevel@tonic-gate	dest[R_G3] = SET_LOWER_32(r->r_g3, src[R_G3]);
2397c478bdstevel@tonic-gate	dest[R_G4] = SET_LOWER_32(r->r_g4, src[R_G4]);
2407c478bdstevel@tonic-gate	dest[R_G5] = SET_LOWER_32(r->r_g5, src[R_G5]);
2417c478bdstevel@tonic-gate	dest[R_G6] = SET_LOWER_32(r->r_g6, src[R_G6]);
2427c478bdstevel@tonic-gate	dest[R_G7] = SET_LOWER_32(r->r_g7, src[R_G7]);
2437c478bdstevel@tonic-gate
2447c478bdstevel@tonic-gate	dest[R_O0] = SET_LOWER_32(r->r_o0, src[R_O0]);
2457c478bdstevel@tonic-gate	dest[R_O1] = SET_LOWER_32(r->r_o1, src[R_O1]);
2467c478bdstevel@tonic-gate	dest[R_O2] = SET_LOWER_32(r->r_o2, src[R_O2]);
2477c478bdstevel@tonic-gate	dest[R_O3] = SET_LOWER_32(r->r_o3, src[R_O3]);
2487c478bdstevel@tonic-gate	dest[R_O4] = SET_LOWER_32(r->r_o4, src[R_O4]);
2497c478bdstevel@tonic-gate	dest[R_O5] = SET_LOWER_32(r->r_o5, src[R_O5]);
2507c478bdstevel@tonic-gate	dest[R_O6] = SET_LOWER_32(r->r_o6, src[R_O6]);
2517c478bdstevel@tonic-gate	dest[R_O7] = SET_LOWER_32(r->r_o7, src[R_O7]);
2527c478bdstevel@tonic-gate
2537c478bdstevel@tonic-gate	if (lwp->lwp_pcb.pcb_xregstat != XREGNONE) {
2547c478bdstevel@tonic-gate		struct rwindow *rw = &lwp->lwp_pcb.pcb_xregs;
2557c478bdstevel@tonic-gate
2567c478bdstevel@tonic-gate		dest[R_L0] = SET_LOWER_32(rw->rw_local[0], src[R_L0]);
2577c478bdstevel@tonic-gate		dest[R_L1] = SET_LOWER_32(rw->rw_local[1], src[R_L1]);
2587c478bdstevel@tonic-gate		dest[R_L2] = SET_LOWER_32(rw->rw_local[2], src[R_L2]);
2597c478bdstevel@tonic-gate		dest[R_L3] = SET_LOWER_32(rw->rw_local[3], src[R_L3]);
2607c478bdstevel@tonic-gate		dest[R_L4] = SET_LOWER_32(rw->rw_local[4], src[R_L4]);
2617c478bdstevel@tonic-gate		dest[R_L5] = SET_LOWER_32(rw->rw_local[5], src[R_L5]);
2627c478bdstevel@tonic-gate		dest[R_L6] = SET_LOWER_32(rw->rw_local[6], src[R_L6]);
2637c478bdstevel@tonic-gate		dest[R_L7] = SET_LOWER_32(rw->rw_local[7], src[R_L7]);
2647c478bdstevel@tonic-gate
2657c478bdstevel@tonic-gate		dest[R_I0] = SET_LOWER_32(rw->rw_in[0], src[R_I0]);
2667c478bdstevel@tonic-gate		dest[R_I1] = SET_LOWER_32(rw->rw_in[1], src[R_I1]);
2677c478bdstevel@tonic-gate		dest[R_I2] = SET_LOWER_32(rw->rw_in[2], src[R_I2]);
2687c478bdstevel@tonic-gate		dest[R_I3] = SET_LOWER_32(rw->rw_in[3], src[R_I3]);
2697c478bdstevel@tonic-gate		dest[R_I4] = SET_LOWER_32(rw->rw_in[4], src[R_I4]);
2707c478bdstevel@tonic-gate		dest[R_I5] = SET_LOWER_32(rw->rw_in[5], src[R_I5]);
2717c478bdstevel@tonic-gate		dest[R_I6] = SET_LOWER_32(rw->rw_in[6], src[R_I6]);
2727c478bdstevel@tonic-gate		dest[R_I7] = SET_LOWER_32(rw->rw_in[7], src[R_I7]);
2737c478bdstevel@tonic-gate	} else {
2747c478bdstevel@tonic-gate		dest[R_L0] = (uint32_t)src[R_L0];
2757c478bdstevel@tonic-gate		dest[R_L1] = (uint32_t)src[R_L1];
2767c478bdstevel@tonic-gate		dest[R_L2] = (uint32_t)src[R_L2];
2777c478bdstevel@tonic-gate		dest[R_L3] = (uint32_t)src[R_L3];
2787c478bdstevel@tonic-gate		dest[R_L4] = (uint32_t)src[R_L4];
2797c478bdstevel@tonic-gate		dest[R_L5] = (uint32_t)src[R_L5];
2807c478bdstevel@tonic-gate		dest[R_L6] = (uint32_t)src[R_L6];
2817c478bdstevel@tonic-gate		dest[R_L7] = (uint32_t)src[R_L7];
2827c478bdstevel@tonic-gate
2837c478bdstevel@tonic-gate		dest[R_I0] = (uint32_t)src[R_I0];
2847c478bdstevel@tonic-gate		dest[R_I1] = (uint32_t)src[R_I1];
2857c478bdstevel@tonic-gate		dest[R_I2] = (uint32_t)src[R_I2];
2867c478bdstevel@tonic-gate		dest[R_I3] = (uint32_t)src[R_I3];
2877c478bdstevel@tonic-gate		dest[R_I4] = (uint32_t)src[R_I4];
2887c478bdstevel@tonic-gate		dest[R_I5] = (uint32_t)src[R_I5];
2897c478bdstevel@tonic-gate		dest[R_I6] = (uint32_t)src[R_I6];
2907c478bdstevel@tonic-gate		dest[R_I7] = (uint32_t)src[R_I7];
2917c478bdstevel@tonic-gate	}
2927c478bdstevel@tonic-gate
2937c478bdstevel@tonic-gate	dest[R_CCR] = ((r->r_tstate >> TSTATE_CCR_SHIFT) & CCR_XCC) |
2947c478bdstevel@tonic-gate	    ((src[R_PSR] >> (TSTATE_CCR_SHIFT-PSR_TSTATE_CC_SHIFT)) & CCR_ICC);
2957c478bdstevel@tonic-gate
2967c478bdstevel@tonic-gate	dest[R_PC] = SET_LOWER_32(r->r_pc, src[R_PC]);
2977c478bdstevel@tonic-gate	dest[R_nPC] = SET_LOWER_32(r->r_npc, src[R_nPC]);
2987c478bdstevel@tonic-gate	dest[R_Y] = (uint32_t)src[R_Y];
2997c478bdstevel@tonic-gate
3007c478bdstevel@tonic-gate	dest[R_ASI] = (r->r_tstate >> TSTATE_ASI_SHIFT) & TSTATE_ASI_MASK;
3017c478bdstevel@tonic-gate	dest[R_FPRS] = lwptofpu(lwp)->fpu_fprs;
3027c478bdstevel@tonic-gate}
3037c478bdstevel@tonic-gate
3047c478bdstevel@tonic-gate/*
3057c478bdstevel@tonic-gate * Return 32-bit general registers.
3067c478bdstevel@tonic-gate */
3077c478bdstevel@tonic-gate
3087c478bdstevel@tonic-gate/* conversion from 64-bit register to 32-bit register */
3097c478bdstevel@tonic-gate#define	R32(r)	(prgreg32_t)(uint32_t)(r)
3107c478bdstevel@tonic-gate
3117c478bdstevel@tonic-gatevoid
3127c478bdstevel@tonic-gateprgetprregs32(klwp_t *lwp, prgregset32_t prp)
3137c478bdstevel@tonic-gate{
3147c478bdstevel@tonic-gate	gregset32_t gr;
3157c478bdstevel@tonic-gate
3167c478bdstevel@tonic-gate	extern void getgregs32(klwp_t *, gregset32_t);
3177c478bdstevel@tonic-gate
3187c478bdstevel@tonic-gate	ASSERT(MUTEX_NOT_HELD(&lwptoproc(lwp)->p_lock));
3197c478bdstevel@tonic-gate
3207c478bdstevel@tonic-gate	getgregs32(lwp, gr);
3214cf53d5Toomas Soome	bzero(prp, NPRGREG * sizeof (*prp));
3227c478bdstevel@tonic-gate
3237c478bdstevel@tonic-gate	/*
3247c478bdstevel@tonic-gate	 * Can't copy since prgregset_t and gregset_t
3257c478bdstevel@tonic-gate	 * use different defines.
3267c478bdstevel@tonic-gate	 */
3277c478bdstevel@tonic-gate	prp[R_G1] = gr[REG_G1];
3287c478bdstevel@tonic-gate	prp[R_G2] = gr[REG_G2];
3297c478bdstevel@tonic-gate	prp[R_G3] = gr[REG_G3];
3307c478bdstevel@tonic-gate	prp[R_G4] = gr[REG_G4];
3317c478bdstevel@tonic-gate	prp[R_G5] = gr[REG_G5];
3327c478bdstevel@tonic-gate	prp[R_G6] = gr[REG_G6];
3337c478bdstevel@tonic-gate	prp[R_G7] = gr[REG_G7];
3347c478bdstevel@tonic-gate
3357c478bdstevel@tonic-gate	prp[R_O0] = gr[REG_O0];
3367c478bdstevel@tonic-gate	prp[R_O1] = gr[REG_O1];
3377c478bdstevel@tonic-gate	prp[R_O2] = gr[REG_O2];
3387c478bdstevel@tonic-gate	prp[R_O3] = gr[REG_O3];
3397c478bdstevel@tonic-gate	prp[R_O4] = gr[REG_O4];
3407c478bdstevel@tonic-gate	prp[R_O5] = gr[REG_O5];
3417c478bdstevel@tonic-gate	prp[R_O6] = gr[REG_O6];
3427c478bdstevel@tonic-gate	prp[R_O7] = gr[REG_O7];
3437c478bdstevel@tonic-gate
3447c478bdstevel@tonic-gate	if (lwp->lwp_pcb.pcb_xregstat != XREGNONE) {
3457c478bdstevel@tonic-gate		prp[R_L0] = R32(lwp->lwp_pcb.pcb_xregs.rw_local[0]);
3467c478bdstevel@tonic-gate		prp[R_L1] = R32(lwp->lwp_pcb.pcb_xregs.rw_local[1]);
3477c478bdstevel@tonic-gate		prp[R_L2] = R32(lwp->lwp_pcb.pcb_xregs.rw_local[2]);
3487c478bdstevel@tonic-gate		prp[R_L3] = R32(lwp->lwp_pcb.pcb_xregs.rw_local[3]);
3497c478bdstevel@tonic-gate		prp[R_L4] = R32(lwp->lwp_pcb.pcb_xregs.rw_local[4]);
3507c478bdstevel@tonic-gate		prp[R_L5] = R32(lwp->lwp_pcb.pcb_xregs.rw_local[5]);
3517c478bdstevel@tonic-gate		prp[R_L6] = R32(lwp->lwp_pcb.pcb_xregs.rw_local[6]);
3527c478bdstevel@tonic-gate		prp[R_L7] = R32(lwp->lwp_pcb.pcb_xregs.rw_local[7]);
3537c478bdstevel@tonic-gate
3547c478bdstevel@tonic-gate		prp[R_I0] = R32(lwp->lwp_pcb.pcb_xregs.rw_in[0]);
3557c478bdstevel@tonic-gate		prp[R_I1] = R32(lwp->lwp_pcb.pcb_xregs.rw_in[1]);
3567c478bdstevel@tonic-gate		prp[R_I2] = R32(lwp->lwp_pcb.pcb_xregs.rw_in[2]);
3577c478bdstevel@tonic-gate		prp[R_I3] = R32(lwp->lwp_pcb.pcb_xregs.rw_in[3]);
3587c478bdstevel@tonic-gate		prp[R_I4] = R32(lwp->lwp_pcb.pcb_xregs.rw_in[4]);
3597c478bdstevel@tonic-gate		prp[R_I5] = R32(lwp->lwp_pcb.pcb_xregs.rw_in[5]);
3607c478bdstevel@tonic-gate		prp[R_I6] = R32(lwp->lwp_pcb.pcb_xregs.rw_in[6]);
3617c478bdstevel@tonic-gate		prp[R_I7] = R32(lwp->lwp_pcb.pcb_xregs.rw_in[7]);
3627c478bdstevel@tonic-gate	}
3637c478bdstevel@tonic-gate
3647c478bdstevel@tonic-gate	prp[R_PSR] = gr[REG_PSR];
3657c478bdstevel@tonic-gate	prp[R_PC]  = gr[REG_PC];
3667c478bdstevel@tonic-gate	prp[R_nPC] = gr[REG_nPC];
3677c478bdstevel@tonic-gate	prp[R_Y]   = gr[REG_Y];
3687c478bdstevel@tonic-gate}
3697c478bdstevel@tonic-gate
3707c478bdstevel@tonic-gate#endif	/* _SYSCALL32_IMPL */
3717c478bdstevel@tonic-gate
3727c478bdstevel@tonic-gate/*
3737c478bdstevel@tonic-gate * Get the syscall return values for the lwp.
3747c478bdstevel@tonic-gate */
3757c478bdstevel@tonic-gateint
3767c478bdstevel@tonic-gateprgetrvals(klwp_t *lwp, long *rval1, long *rval2)
3777c478bdstevel@tonic-gate{
3787c478bdstevel@tonic-gate	struct regs *r = lwptoregs(lwp);
3797c478bdstevel@tonic-gate
3807c478bdstevel@tonic-gate	if (r->r_tstate & TSTATE_IC)
3817c478bdstevel@tonic-gate		return ((int)r->r_o0);
3827c478bdstevel@tonic-gate	if (lwp->lwp_eosys == JUSTRETURN) {
3837c478bdstevel@tonic-gate		*rval1 = 0;
3847c478bdstevel@tonic-gate		*rval2 = 0;
3857c478bdstevel@tonic-gate	} else if (lwptoproc(lwp)->p_model == DATAMODEL_ILP32) {
3867c478bdstevel@tonic-gate		*rval1 = r->r_o0 & (uint32_t)0xffffffffU;
3877c478bdstevel@tonic-gate		*rval2 = r->r_o1 & (uint32_t)0xffffffffU;
3887c478bdstevel@tonic-gate	} else {
3897c478bdstevel@tonic-gate		*rval1 = r->r_o0;
3907c478bdstevel@tonic-gate		*rval2 = r->r_o1;
3917c478bdstevel@tonic-gate	}
3927c478bdstevel@tonic-gate	return (0);
3937c478bdstevel@tonic-gate}
3947c478bdstevel@tonic-gate
3957c478bdstevel@tonic-gate/*
3967c478bdstevel@tonic-gate * Does the system support floating-point, either through hardware
3977c478bdstevel@tonic-gate * or by trapping and emulating floating-point machine instructions?
3987c478bdstevel@tonic-gate */
3997c478bdstevel@tonic-gateint
4007c478bdstevel@tonic-gateprhasfp(void)
4017c478bdstevel@tonic-gate{
4027c478bdstevel@tonic-gate	/*
4037c478bdstevel@tonic-gate	 * SunOS5.0 emulates floating-point if FP hardware is not present.
4047c478bdstevel@tonic-gate	 */
4057c478bdstevel@tonic-gate	return (1);
4067c478bdstevel@tonic-gate}
4077c478bdstevel@tonic-gate
4087c478bdstevel@tonic-gate/*
4097c478bdstevel@tonic-gate * Get floating-point registers.
4107c478bdstevel@tonic-gate */
4117c478bdstevel@tonic-gatevoid
4127c478bdstevel@tonic-gateprgetprfpregs(klwp_t *lwp, prfpregset_t *pfp)
4137c478bdstevel@tonic-gate{
4147c478bdstevel@tonic-gate	bzero(pfp, sizeof (*pfp));
4157c478bdstevel@tonic-gate	/*
4167c478bdstevel@tonic-gate	 * This works only because prfpregset_t is intentionally
4177c478bdstevel@tonic-gate	 * constructed to be identical to fpregset_t, with additional
4187c478bdstevel@tonic-gate	 * space for the floating-point queue at the end.
4197c478bdstevel@tonic-gate	 */
4207c478bdstevel@tonic-gate	getfpregs(lwp, (fpregset_t *)pfp);
4217c478bdstevel@tonic-gate	/*
4227c478bdstevel@tonic-gate	 * This is supposed to be a pointer to the floating point queue.
4237c478bdstevel@tonic-gate	 * We can't provide such a thing through the /proc interface.
4247c478bdstevel@tonic-gate	 */
4251255103Toomas Soome	pfp->pr_filler = 0;
4267c478bdstevel@tonic-gate	/*
4277c478bdstevel@tonic-gate	 * XXX: to be done: fetch the FP queue if it is non-empty.
4287c478bdstevel@tonic-gate	 */
4297c478bdstevel@tonic-gate}
4307c478bdstevel@tonic-gate
4317c478bdstevel@tonic-gate#ifdef	_SYSCALL32_IMPL
4327c478bdstevel@tonic-gatevoid
4337c478bdstevel@tonic-gateprgetprfpregs32(klwp_t *lwp, prfpregset32_t *pfp)
4347c478bdstevel@tonic-gate{
4357c478bdstevel@tonic-gate	bzero(pfp, sizeof (*pfp));
4367c478bdstevel@tonic-gate	/*
4377c478bdstevel@tonic-gate	 * This works only because prfpregset32_t is intentionally
4387c478bdstevel@tonic-gate	 * constructed to be identical to fpregset32_t, with additional
4397c478bdstevel@tonic-gate	 * space for the floating-point queue at the end.
4407c478bdstevel@tonic-gate	 */
4417c478bdstevel@tonic-gate	getfpregs32(lwp, (fpregset32_t *)pfp);
4427c478bdstevel@tonic-gate	/*
4437c478bdstevel@tonic-gate	 * This is supposed to be a pointer to the floating point queue.
4447c478bdstevel@tonic-gate	 * We can't provide such a thing through the /proc interface.
4457c478bdstevel@tonic-gate	 */
4461255103Toomas Soome	pfp->pr_filler = 0;
4477c478bdstevel@tonic-gate	/*
4487c478bdstevel@tonic-gate	 * XXX: to be done: fetch the FP queue if it is non-empty.
4497c478bdstevel@tonic-gate	 */
4507c478bdstevel@tonic-gate}
4517c478bdstevel@tonic-gate#endif	/* _SYSCALL32_IMPL */
4527c478bdstevel@tonic-gate
4537c478bdstevel@tonic-gate/*
4547c478bdstevel@tonic-gate * Set floating-point registers.
4557c478bdstevel@tonic-gate */
4567c478bdstevel@tonic-gatevoid
4577c478bdstevel@tonic-gateprsetprfpregs(klwp_t *lwp, prfpregset_t *pfp)
4587c478bdstevel@tonic-gate{
4597c478bdstevel@tonic-gate	/*
4607c478bdstevel@tonic-gate	 * XXX: to be done: store the FP queue if it is non-empty.
4617c478bdstevel@tonic-gate	 */
4627c478bdstevel@tonic-gate	pfp->pr_qcnt = 0;
4637c478bdstevel@tonic-gate	/*
4647c478bdstevel@tonic-gate	 * We set fpu_en before calling setfpregs() in order to
4657c478bdstevel@tonic-gate	 * retain the semantics of this operation from older
4667c478bdstevel@tonic-gate	 * versions of the system.  SunOS 5.4 and prior never
4677c478bdstevel@tonic-gate	 * queried fpu_en; they just set the registers.  The
4687c478bdstevel@tonic-gate	 * proper operation if fpu_en is zero is to disable
4697c478bdstevel@tonic-gate	 * floating point in the target process, but this can
4707c478bdstevel@tonic-gate	 * only change after a proper end-of-life period for
4717c478bdstevel@tonic-gate	 * the old semantics.
4727c478bdstevel@tonic-gate	 */
4737c478bdstevel@tonic-gate	pfp->pr_en = 1;
4747c478bdstevel@tonic-gate	/*
4757c478bdstevel@tonic-gate	 * This works only because prfpregset_t is intentionally
4767c478bdstevel@tonic-gate	 * constructed to be identical to fpregset_t, with additional
4777c478bdstevel@tonic-gate	 * space for the floating-point queue at the end.
4787c478bdstevel@tonic-gate	 */
4797c478bdstevel@tonic-gate	setfpregs(lwp, (fpregset_t *)pfp);
4807c478bdstevel@tonic-gate}
4817c478bdstevel@tonic-gate
4827c478bdstevel@tonic-gate#ifdef	_SYSCALL32_IMPL
4837c478bdstevel@tonic-gatevoid
4847c478bdstevel@tonic-gateprsetprfpregs32(klwp_t *lwp, prfpregset32_t *pfp)
4857c478bdstevel@tonic-gate{
4867c478bdstevel@tonic-gate	/*
4877c478bdstevel@tonic-gate	 * XXX: to be done: store the FP queue if it is non-empty.
4887c478bdstevel@tonic-gate	 */
4897c478bdstevel@tonic-gate	pfp->pr_qcnt = 0;
4907c478bdstevel@tonic-gate	/*
4917c478bdstevel@tonic-gate	 * We set fpu_en before calling setfpregs() in order to
4927c478bdstevel@tonic-gate	 * retain the semantics of this operation from older
4937c478bdstevel@tonic-gate	 * versions of the system.  SunOS 5.4 and prior never
4947c478bdstevel@tonic-gate	 * queried fpu_en; they just set the registers.  The
4957c478bdstevel@tonic-gate	 * proper operation if fpu_en is zero is to disable
4967c478bdstevel@tonic-gate	 * floating point in the target process, but this can
4977c478bdstevel@tonic-gate	 * only change after a proper end-of-life period for
4987c478bdstevel@tonic-gate	 * the old semantics.
4997c478bdstevel@tonic-gate	 */
5007c478bdstevel@tonic-gate	pfp->pr_en = 1;
5017c478bdstevel@tonic-gate	/*
5027c478bdstevel@tonic-gate	 * This works only because prfpregset32_t is intentionally
5037c478bdstevel@tonic-gate	 * constructed to be identical to fpregset32_t, with additional
5047c478bdstevel@tonic-gate	 * space for the floating-point queue at the end.
5057c478bdstevel@tonic-gate	 */
5067c478bdstevel@tonic-gate	setfpregs32(lwp, (fpregset32_t *)pfp);
5077c478bdstevel@tonic-gate}
5087c478bdstevel@tonic-gate#endif	/* _SYSCALL32_IMPL */
5097c478bdstevel@tonic-gate
5107c478bdstevel@tonic-gate/*
5117c478bdstevel@tonic-gate * Does the system support extra register state?
5127c478bdstevel@tonic-gate * In a kernel that supports both an _LP64 and an _ILP32 data model,
5137c478bdstevel@tonic-gate * the answer depends on the data model of the process.
5147c478bdstevel@tonic-gate * An _LP64 process does not have extra registers.
5157c478bdstevel@tonic-gate */
5167c478bdstevel@tonic-gateint
5177c478bdstevel@tonic-gateprhasx(proc_t *p)
5187c478bdstevel@tonic-gate{
5197c478bdstevel@tonic-gate	extern int xregs_exists;
5207c478bdstevel@tonic-gate
5217c478bdstevel@tonic-gate	if (p->p_model == DATAMODEL_LP64)
5227c478bdstevel@tonic-gate		return (0);
5237c478bdstevel@tonic-gate	else
5247c478bdstevel@tonic-gate		return (xregs_exists);
5257c478bdstevel@tonic-gate}
5267c478bdstevel@tonic-gate
5277c478bdstevel@tonic-gate/*
5287c478bdstevel@tonic-gate * Get the size of the extra registers.
5297c478bdstevel@tonic-gate */
5307c478bdstevel@tonic-gateint
5317c478bdstevel@tonic-gateprgetprxregsize(proc_t *p)
5327c478bdstevel@tonic-gate{
5337c478bdstevel@tonic-gate	return (xregs_getsize(p));
5347c478bdstevel@tonic-gate}
5357c478bdstevel@tonic-gate
5367c478bdstevel@tonic-gate/*
5377c478bdstevel@tonic-gate * Get extra registers.
5387c478bdstevel@tonic-gate */
5397c478bdstevel@tonic-gatevoid
5407c478bdstevel@tonic-gateprgetprxregs(klwp_t *lwp, caddr_t prx)
5417c478bdstevel@tonic-gate{
5427c478bdstevel@tonic-gate	extern void xregs_get(struct _klwp *, caddr_t);
5437c478bdstevel@tonic-gate
5447c478bdstevel@tonic-gate	(void) xregs_get(lwp, prx);
5457c478bdstevel@tonic-gate}
5467c478bdstevel@tonic-gate
5477c478bdstevel@tonic-gate/*
5487c478bdstevel@tonic-gate * Set extra registers.
5497c478bdstevel@tonic-gate */
5507c478bdstevel@tonic-gatevoid
5517c478bdstevel@tonic-gateprsetprxregs(klwp_t *lwp, caddr_t prx)
5527c478bdstevel@tonic-gate{
5537c478bdstevel@tonic-gate	extern void xregs_set(struct _klwp *, caddr_t);
5547c478bdstevel@tonic-gate
5557c478bdstevel@tonic-gate	(void) xregs_set(lwp, prx);
5567c478bdstevel@tonic-gate}
5577c478bdstevel@tonic-gate
5587c478bdstevel@tonic-gate/*
5597c478bdstevel@tonic-gate * Get the ancillary state registers.
5607c478bdstevel@tonic-gate */
5617c478bdstevel@tonic-gatevoid
5627c478bdstevel@tonic-gateprgetasregs(klwp_t *lwp, asrset_t asrset)
5637c478bdstevel@tonic-gate{
5647c478bdstevel@tonic-gate	bzero(asrset, sizeof (asrset_t));
5657c478bdstevel@tonic-gate	getasrs(lwp, asrset);
5667c478bdstevel@tonic-gate	getfpasrs(lwp, asrset);
5677c478bdstevel@tonic-gate}
5687c478bdstevel@tonic-gate
5697c478bdstevel@tonic-gate/*
5707c478bdstevel@tonic-gate * Set the ancillary state registers.
5717c478bdstevel@tonic-gate */
5727c478bdstevel@tonic-gatevoid
5737c478bdstevel@tonic-gateprsetasregs(klwp_t *lwp, asrset_t asrset)
5747c478bdstevel@tonic-gate{
5757c478bdstevel@tonic-gate	setasrs(lwp, asrset);
5767c478bdstevel@tonic-gate	setfpasrs(lwp, asrset);
5777c478bdstevel@tonic-gate}
5787c478bdstevel@tonic-gate
5797c478bdstevel@tonic-gate/*
5807c478bdstevel@tonic-gate * Return the base (lower limit) of the process stack.
5817c478bdstevel@tonic-gate */
5827c478bdstevel@tonic-gatecaddr_t
5837c478bdstevel@tonic-gateprgetstackbase(proc_t *p)
5847c478bdstevel@tonic-gate{
5857c478bdstevel@tonic-gate	return (p->p_usrstack - p->p_stksize);
5867c478bdstevel@tonic-gate}
5877c478bdstevel@tonic-gate
5887c478bdstevel@tonic-gate/*
5897c478bdstevel@tonic-gate * Return the "addr" field for pr_addr in prpsinfo_t.
5907c478bdstevel@tonic-gate * This is a vestige of the past, so whatever we return is OK.
5917c478bdstevel@tonic-gate */
5927c478bdstevel@tonic-gatecaddr_t
5937c478bdstevel@tonic-gateprgetpsaddr(proc_t *p)
5947c478bdstevel@tonic-gate{
5957c478bdstevel@tonic-gate	return ((caddr_t)p);
5967c478bdstevel@tonic-gate}
5977c478bdstevel@tonic-gate
5987c478bdstevel@tonic-gate/*
5997c478bdstevel@tonic-gate * Arrange to single-step the lwp.
6007c478bdstevel@tonic-gate */
6017c478bdstevel@tonic-gatevoid
6027c478bdstevel@tonic-gateprstep(klwp_t *lwp, int watchstep)
6037c478bdstevel@tonic-gate{
6047c478bdstevel@tonic-gate	ASSERT(MUTEX_NOT_HELD(&lwptoproc(lwp)->p_lock));
6057c478bdstevel@tonic-gate
6067c478bdstevel@tonic-gate	lwp->lwp_pcb.pcb_step = STEP_REQUESTED;
6077c478bdstevel@tonic-gate	lwp->lwp_pcb.pcb_tracepc = NULL;
6087c478bdstevel@tonic-gate	if (watchstep)
6097c478bdstevel@tonic-gate		lwp->lwp_pcb.pcb_flags |= WATCH_STEP;
6107c478bdstevel@tonic-gate	else
6117c478bdstevel@tonic-gate		lwp->lwp_pcb.pcb_flags |= NORMAL_STEP;
6127c478bdstevel@tonic-gate}
6137c478bdstevel@tonic-gate
6147c478bdstevel@tonic-gate/*
6157c478bdstevel@tonic-gate * Undo prstep().
6167c478bdstevel@tonic-gate */
6177c478bdstevel@tonic-gatevoid
6187c478bdstevel@tonic-gateprnostep(klwp_t *lwp)
6197c478bdstevel@tonic-gate{
6207c478bdstevel@tonic-gate	ASSERT(ttolwp(curthread) == lwp ||
6217c478bdstevel@tonic-gate	    MUTEX_NOT_HELD(&lwptoproc(lwp)->p_lock));
6227c478bdstevel@tonic-gate
6237c478bdstevel@tonic-gate	lwp->lwp_pcb.pcb_step = STEP_NONE;
6247c478bdstevel@tonic-gate	lwp->lwp_pcb.pcb_tracepc = NULL;
6257c478bdstevel@tonic-gate	lwp->lwp_pcb.pcb_flags &= ~(NORMAL_STEP|WATCH_STEP);
6267c478bdstevel@tonic-gate}
6277c478bdstevel@tonic-gate
6287c478bdstevel@tonic-gate/*
6297c478bdstevel@tonic-gate * Return non-zero if a single-step is in effect.
6307c478bdstevel@tonic-gate */
6317c478bdstevel@tonic-gateint
6327c478bdstevel@tonic-gateprisstep(klwp_t *lwp)
6337c478bdstevel@tonic-gate{
6347c478bdstevel@tonic-gate	ASSERT(MUTEX_NOT_HELD(&lwptoproc(lwp)->p_lock));
6357c478bdstevel@tonic-gate
6367c478bdstevel@tonic-gate	return (lwp->lwp_pcb.pcb_step != STEP_NONE);
6377c478bdstevel@tonic-gate}
6387c478bdstevel@tonic-gate
6397c478bdstevel@tonic-gate/*
6407c478bdstevel@tonic-gate * Set the PC to the specified virtual address.
6417c478bdstevel@tonic-gate */
6427c478bdstevel@tonic-gatevoid
6437c478bdstevel@tonic-gateprsvaddr(klwp_t *lwp, caddr_t vaddr)
6447c478bdstevel@tonic-gate{
6457c478bdstevel@tonic-gate	struct regs *r = lwptoregs(lwp);
6467c478bdstevel@tonic-gate
6477c478bdstevel@tonic-gate	ASSERT(MUTEX_NOT_HELD(&lwptoproc(lwp)->p_lock));
6487c478bdstevel@tonic-gate
6497c478bdstevel@tonic-gate	/*
6507c478bdstevel@tonic-gate	 * pc and npc must be word aligned on sparc.
6517c478bdstevel@tonic-gate	 * We silently make it so to avoid a watchdog reset.
6527c478bdstevel@tonic-gate	 */
6537c478bdstevel@tonic-gate	r->r_pc = (uintptr_t)vaddr & ~03L;
6547c478bdstevel@tonic-gate	r->r_npc = r->r_pc + 4;
6557c478bdstevel@tonic-gate}
6567c478bdstevel@tonic-gate
6577c478bdstevel@tonic-gate/*
6587c478bdstevel@tonic-gate * Map address "addr" in address space "as" into a kernel virtual address.
6597c478bdstevel@tonic-gate * The memory is guaranteed to be resident and locked down.
6607c478bdstevel@tonic-gate */
6617c478bdstevel@tonic-gatecaddr_t
6627c478bdstevel@tonic-gateprmapin(struct as *as, caddr_t addr, int writing)
6637c478bdstevel@tonic-gate{
6647c478bdstevel@tonic-gate	page_t *pp;
6657c478bdstevel@tonic-gate	caddr_t kaddr;
6667c478bdstevel@tonic-gate	pfn_t pfnum;
6677c478bdstevel@tonic-gate
6687c478bdstevel@tonic-gate	/*
6697c478bdstevel@tonic-gate	 * XXX - Because of past mistakes, we have bits being returned
6707c478bdstevel@tonic-gate	 * by getpfnum that are actually the page type bits of the pte.
6717c478bdstevel@tonic-gate	 * When the object we are trying to map is a memory page with
6727c478bdstevel@tonic-gate	 * a page structure everything is ok and we can use the optimal
6737c478bdstevel@tonic-gate	 * method, ppmapin.  Otherwise, we have to do something special.
6747c478bdstevel@tonic-gate	 */
6757c478bdstevel@tonic-gate	pfnum = hat_getpfnum(as->a_hat, addr);
6767c478bdstevel@tonic-gate	if (pf_is_memory(pfnum)) {
6777c478bdstevel@tonic-gate		pp = page_numtopp_nolock(pfnum);
6787c478bdstevel@tonic-gate		if (pp != NULL) {
6797c478bdstevel@tonic-gate			ASSERT(PAGE_LOCKED(pp));
6807c478bdstevel@tonic-gate			kaddr = ppmapin(pp, writing ?
6812c5124aPrashanth Sreenivasa			    (PROT_READ | PROT_WRITE) : PROT_READ,
6822c5124aPrashanth Sreenivasa			    (caddr_t)-1);
6837c478bdstevel@tonic-gate			return (kaddr + ((uintptr_t)addr & PAGEOFFSET));
6847c478bdstevel@tonic-gate		}
6857c478bdstevel@tonic-gate	}
6867c478bdstevel@tonic-gate
6877c478bdstevel@tonic-gate	/*
6887c478bdstevel@tonic-gate	 * Oh well, we didn't have a page struct for the object we were
6897c478bdstevel@tonic-gate	 * trying to map in; ppmapin doesn't handle devices, but allocating a
6907c478bdstevel@tonic-gate	 * heap address allows ppmapout to free virutal space when done.
6917c478bdstevel@tonic-gate	 */
6927c478bdstevel@tonic-gate	kaddr = vmem_alloc(heap_arena, PAGESIZE, VM_SLEEP);
6937c478bdstevel@tonic-gate
6947c478bdstevel@tonic-gate	hat_devload(kas.a_hat, kaddr, PAGESIZE, pfnum,
6952c5124aPrashanth Sreenivasa	    writing ? (PROT_READ | PROT_WRITE) : PROT_READ, HAT_LOAD_LOCK);
6967c478bdstevel@tonic-gate
6977c478bdstevel@tonic-gate	return (kaddr + ((uintptr_t)addr & PAGEOFFSET));
6987c478bdstevel@tonic-gate}
6997c478bdstevel@tonic-gate
7007c478bdstevel@tonic-gate/*
7017c478bdstevel@tonic-gate * Unmap address "addr" in address space "as"; inverse of prmapin().
7027c478bdstevel@tonic-gate */
7037c478bdstevel@tonic-gate/* ARGSUSED */
7047c478bdstevel@tonic-gatevoid
7057c478bdstevel@tonic-gateprmapout(struct as *as, caddr_t addr, caddr_t vaddr, int writing)
7067c478bdstevel@tonic-gate{
7077c478bdstevel@tonic-gate	extern void ppmapout(caddr_t);
7087c478bdstevel@tonic-gate
7097c478bdstevel@tonic-gate	vaddr = (caddr_t)((uintptr_t)vaddr & PAGEMASK);
7107c478bdstevel@tonic-gate	ppmapout(vaddr);
7117c478bdstevel@tonic-gate}
7127c478bdstevel@tonic-gate
7137c478bdstevel@tonic-gate
7147c478bdstevel@tonic-gate#define	BAMASK22 0xffc00000	/* for masking out disp22 from ba,a */
7157c478bdstevel@tonic-gate#define	BAA	0x30800000	/* ba,a without disp22 */
7167c478bdstevel@tonic-gate#define	FBAA	0x31800000	/* fba,a without disp22 */
7177c478bdstevel@tonic-gate#define	CBAA	0x31c00000	/* cba,a without disp22 */
7187c478bdstevel@tonic-gate
7197c478bdstevel@tonic-gate#define	BAMASK19 0xfff80000	/* for masking out disp19 from ba,a %[ix]cc */
7207c478bdstevel@tonic-gate#define	BAA_icc	0x30480000	/* ba,a %icc without disp19 */
7217c478bdstevel@tonic-gate#define	BAA_xcc	0x30680000	/* ba,a %xcc without disp19 */
7227c478bdstevel@tonic-gate
7237c478bdstevel@tonic-gate
7247c478bdstevel@tonic-gate/*
7257c478bdstevel@tonic-gate * Prepare to single-step the lwp if requested.
7267c478bdstevel@tonic-gate * This is called by the lwp itself just before returning to user level.
7277c478bdstevel@tonic-gate */
7287c478bdstevel@tonic-gatevoid
7297c478bdstevel@tonic-gateprdostep(void)
7307c478bdstevel@tonic-gate{
7317c478bdstevel@tonic-gate	klwp_t *lwp = ttolwp(curthread);
7327c478bdstevel@tonic-gate	struct regs *r = lwptoregs(lwp);
7337c478bdstevel@tonic-gate	proc_t *p = lwptoproc(lwp);
7347c478bdstevel@tonic-gate	struct as *as = p->p_as;
7357c478bdstevel@tonic-gate	caddr_t pc;
7367c478bdstevel@tonic-gate	caddr_t npc;
7377c478bdstevel@tonic-gate
7387c478bdstevel@tonic-gate	ASSERT(lwp != NULL);
7397c478bdstevel@tonic-gate	ASSERT(r != NULL);
7407c478bdstevel@tonic-gate
7417c478bdstevel@tonic-gate	if (lwp->lwp_pcb.pcb_step == STEP_NONE ||
7427c478bdstevel@tonic-gate	    lwp->lwp_pcb.pcb_step == STEP_ACTIVE)
7437c478bdstevel@tonic-gate		return;
7447c478bdstevel@tonic-gate
7457c478bdstevel@tonic-gate	if (p->p_model == DATAMODEL_ILP32) {
7467552190raf		pc = (caddr_t)(uintptr_t)(caddr32_t)r->r_pc;
7477552190raf		npc = (caddr_t)(uintptr_t)(caddr32_t)r->r_npc;
7487c478bdstevel@tonic-gate	} else {
7497c478bdstevel@tonic-gate		pc = (caddr_t)r->r_pc;
7507c478bdstevel@tonic-gate		npc = (caddr_t)r->r_npc;
7517c478bdstevel@tonic-gate	}
7527c478bdstevel@tonic-gate
7537c478bdstevel@tonic-gate	if (lwp->lwp_pcb.pcb_step == STEP_WASACTIVE) {
7547c478bdstevel@tonic-gate		if (npc == (caddr_t)lwp->lwp_pcb.pcb_tracepc)
7557c478bdstevel@tonic-gate			r->r_npc = (greg_t)as->a_userlimit;
7567c478bdstevel@tonic-gate		else {
7577c478bdstevel@tonic-gate			lwp->lwp_pcb.pcb_tracepc = (void *)pc;
7587c478bdstevel@tonic-gate			r->r_pc = (greg_t)as->a_userlimit;
7597c478bdstevel@tonic-gate		}
7607c478bdstevel@tonic-gate	} else {
7617c478bdstevel@tonic-gate		/*
7627c478bdstevel@tonic-gate		 * Single-stepping on sparc is effected by setting nPC
7637c478bdstevel@tonic-gate		 * to an invalid address and expecting FLTBOUNDS to
7647c478bdstevel@tonic-gate		 * occur after the instruction at PC is executed.
7657c478bdstevel@tonic-gate		 * This is not the whole story, however; we must
7667c478bdstevel@tonic-gate		 * deal with branch-always instructions with the
7677c478bdstevel@tonic-gate		 * annul bit set as a special case here.
7687c478bdstevel@tonic-gate		 *
7697c478bdstevel@tonic-gate		 * fuword() returns -1 on error and we can't distinguish
7707c478bdstevel@tonic-gate		 * this from a legitimate instruction of all 1's.
7717c478bdstevel@tonic-gate		 * However 0xffffffff is not one of the branch-always
7727c478bdstevel@tonic-gate		 * instructions we are interested in.  No problem.
7737c478bdstevel@tonic-gate		 */
7747c478bdstevel@tonic-gate		int32_t instr;
7757c478bdstevel@tonic-gate		int32_t i;
7767c478bdstevel@tonic-gate
7777c478bdstevel@tonic-gate		if (fuword32_nowatch((void *)pc, (uint32_t *)&instr) != 0)
7787c478bdstevel@tonic-gate			instr = -1;
7797c478bdstevel@tonic-gate		if ((i = instr & BAMASK22) == BAA || i == FBAA || i == CBAA) {
7807c478bdstevel@tonic-gate			/*
7817c478bdstevel@tonic-gate			 * For ba,a and relatives, compute the
7827c478bdstevel@tonic-gate			 * new PC from the instruction.
7837c478bdstevel@tonic-gate			 */
7847c478bdstevel@tonic-gate			i = (instr << 10) >> 8;
7857c478bdstevel@tonic-gate			lwp->lwp_pcb.pcb_tracepc = (void *)(pc + i);
7867c478bdstevel@tonic-gate			r->r_pc = (greg_t)as->a_userlimit;
7877c478bdstevel@tonic-gate			r->r_npc = r->r_pc + 4;
7887c478bdstevel@tonic-gate		} else if ((i = instr & BAMASK19) == BAA_icc || i == BAA_xcc) {
7897c478bdstevel@tonic-gate			/*
7907c478bdstevel@tonic-gate			 * For ba,a %icc and ba,a %xcc, compute the
7917c478bdstevel@tonic-gate			 * new PC from the instruction.
7927c478bdstevel@tonic-gate			 */
7937c478bdstevel@tonic-gate			i = (instr << 13) >> 11;
7947c478bdstevel@tonic-gate			lwp->lwp_pcb.pcb_tracepc = (void *)(pc + i);
7957c478bdstevel@tonic-gate			r->r_pc = (greg_t)as->a_userlimit;
7967c478bdstevel@tonic-gate			r->r_npc = r->r_pc + 4;
7977c478bdstevel@tonic-gate		} else {
7987c478bdstevel@tonic-gate			lwp->lwp_pcb.pcb_tracepc = (void *)npc;
7997c478bdstevel@tonic-gate			r->r_npc = (greg_t)as->a_userlimit;
8007c478bdstevel@tonic-gate		}
8017c478bdstevel@tonic-gate	}
8027c478bdstevel@tonic-gate
8037c478bdstevel@tonic-gate	lwp->lwp_pcb.pcb_step = STEP_ACTIVE;
8047c478bdstevel@tonic-gate}
8057c478bdstevel@tonic-gate
8067c478bdstevel@tonic-gate/*
8077c478bdstevel@tonic-gate * Wrap up single stepping of the lwp.
8087c478bdstevel@tonic-gate * This is called by the lwp itself just after it has taken
8097c478bdstevel@tonic-gate * the FLTBOUNDS trap.  We fix up the PC and nPC to have their
8107c478bdstevel@tonic-gate * proper values after the step.  We return 1 to indicate that
8117c478bdstevel@tonic-gate * this fault really is the one we are expecting, else 0.
8127c478bdstevel@tonic-gate *
8137c478bdstevel@tonic-gate * This is also called from syscall() and stop() to reset PC
8147c478bdstevel@tonic-gate * and nPC to their proper values for debugger visibility.
8157c478bdstevel@tonic-gate */
8167c478bdstevel@tonic-gateint
8177c478bdstevel@tonic-gateprundostep(void)
8187c478bdstevel@tonic-gate{
8197c478bdstevel@tonic-gate	klwp_t *lwp = ttolwp(curthread);
8207c478bdstevel@tonic-gate	proc_t *p = ttoproc(curthread);
8217c478bdstevel@tonic-gate	struct as *as = p->p_as;
8227c478bdstevel@tonic-gate	int rc = 0;
8237c478bdstevel@tonic-gate	caddr_t pc;
8247c478bdstevel@tonic-gate	caddr_t npc;
8257c478bdstevel@tonic-gate
8267c478bdstevel@tonic-gate	ASSERT(lwp != NULL);
8277c478bdstevel@tonic-gate
8287c478bdstevel@tonic-gate	if (lwp->lwp_pcb.pcb_step == STEP_ACTIVE) {
8297c478bdstevel@tonic-gate		struct regs *r = lwptoregs(lwp);
8307c478bdstevel@tonic-gate
8317c478bdstevel@tonic-gate		ASSERT(r != NULL);
8327c478bdstevel@tonic-gate
8337c478bdstevel@tonic-gate		if (p->p_model == DATAMODEL_ILP32) {
8347552190raf			pc = (caddr_t)(uintptr_t)(caddr32_t)r->r_pc;
8357552190raf			npc = (caddr_t)(uintptr_t)(caddr32_t)r->r_npc;
8367c478bdstevel@tonic-gate		} else {
8377c478bdstevel@tonic-gate			pc = (caddr_t)r->r_pc;
8387c478bdstevel@tonic-gate			npc = (caddr_t)r->r_npc;
8397c478bdstevel@tonic-gate		}
8407c478bdstevel@tonic-gate
8417c478bdstevel@tonic-gate		if (pc == (caddr_t)as->a_userlimit ||
8427c478bdstevel@tonic-gate		    pc == (caddr_t)as->a_userlimit + 4) {
8437c478bdstevel@tonic-gate			if (pc == (caddr_t)as->a_userlimit) {
8447c478bdstevel@tonic-gate				r->r_pc = (greg_t)lwp->lwp_pcb.pcb_tracepc;
8457c478bdstevel@tonic-gate				if (npc == (caddr_t)as->a_userlimit + 4)
8467c478bdstevel@tonic-gate					r->r_npc = r->r_pc + 4;
8477c478bdstevel@tonic-gate			} else {
8487c478bdstevel@tonic-gate				r->r_pc = (greg_t)lwp->lwp_pcb.pcb_tracepc + 4;
8497c478bdstevel@tonic-gate				r->r_npc = r->r_pc + 4;
8507c478bdstevel@tonic-gate			}
8517c478bdstevel@tonic-gate			rc = 1;
8527c478bdstevel@tonic-gate		} else {
8537c478bdstevel@tonic-gate			r->r_npc = (greg_t)lwp->lwp_pcb.pcb_tracepc;
8547c478bdstevel@tonic-gate		}
8557c478bdstevel@tonic-gate		lwp->lwp_pcb.pcb_step = STEP_WASACTIVE;
8567c478bdstevel@tonic-gate	}
8577c478bdstevel@tonic-gate
8587c478bdstevel@tonic-gate	return (rc);
8597c478bdstevel@tonic-gate}
8607c478bdstevel@tonic-gate
8617c478bdstevel@tonic-gate/*
8627c478bdstevel@tonic-gate * Make sure the lwp is in an orderly state
8637c478bdstevel@tonic-gate * for inspection by a debugger through /proc.
86407a4882Roger A. Faulkner *
86507a4882Roger A. Faulkner * This needs to be called only once while the current thread remains in the
86607a4882Roger A. Faulkner * kernel and needs to be called while holding no resources (mutex locks, etc).
86707a4882Roger A. Faulkner *
86807a4882Roger A. Faulkner * As a hedge against these conditions, if prstop() is called repeatedly
86907a4882Roger A. Faulkner * before prunstop() is called, it does nothing and just returns.
87007a4882Roger A. Faulkner *
87107a4882Roger A. Faulkner * prunstop() must be called before the thread returns to user level.
8727c478bdstevel@tonic-gate */
8737c478bdstevel@tonic-gate/* ARGSUSED */
8747c478bdstevel@tonic-gatevoid
8757c478bdstevel@tonic-gateprstop(int why, int what)
8767c478bdstevel@tonic-gate{
8777c478bdstevel@tonic-gate	klwp_t *lwp = ttolwp(curthread);
8787c478bdstevel@tonic-gate	proc_t *p = lwptoproc(lwp);
8797c478bdstevel@tonic-gate	struct regs *r = lwptoregs(lwp);
8807c478bdstevel@tonic-gate	kfpu_t *pfp = lwptofpu(lwp);
8817c478bdstevel@tonic-gate	caddr_t sp;
8827c478bdstevel@tonic-gate	caddr_t pc;
8837c478bdstevel@tonic-gate	int watched;
8847c478bdstevel@tonic-gate	extern void fp_prsave(kfpu_t *);
8857c478bdstevel@tonic-gate
88607a4882Roger A. Faulkner	if (lwp->lwp_pcb.pcb_flags & PRSTOP_CALLED)
88707a4882Roger A. Faulkner		return;
88807a4882Roger A. Faulkner
8897c478bdstevel@tonic-gate	/*
8908548bf7nr	 * Make sure we don't deadlock on a recursive call
8918548bf7nr	 * to prstop().  stop() tests the lwp_nostop flag.
8927c478bdstevel@tonic-gate	 */
8938548bf7nr	ASSERT(lwp->lwp_nostop == 0);
8948548bf7nr	lwp->lwp_nostop = 1;
8957c478bdstevel@tonic-gate	(void) flush_user_windows_to_stack(NULL);
8967c478bdstevel@tonic-gate	if (lwp->lwp_pcb.pcb_step != STEP_NONE)
8977c478bdstevel@tonic-gate		(void) prundostep();
8987c478bdstevel@tonic-gate
8997c478bdstevel@tonic-gate	if (lwp->lwp_pcb.pcb_xregstat == XREGNONE) {
9007c478bdstevel@tonic-gate		/*
9017c478bdstevel@tonic-gate		 * Attempt to fetch the last register window from the stack.
9027c478bdstevel@tonic-gate		 * If that fails, look for it in the pcb.
9037c478bdstevel@tonic-gate		 * If that fails, give up.
9047c478bdstevel@tonic-gate		 */
9057c478bdstevel@tonic-gate		struct machpcb *mpcb = lwptompcb(lwp);
9067c478bdstevel@tonic-gate		struct rwindow32 rwindow32;
9077c478bdstevel@tonic-gate		size_t rw_size;
9087c478bdstevel@tonic-gate		caddr_t rwp;
9097c478bdstevel@tonic-gate		int is64;
9107c478bdstevel@tonic-gate
9117c478bdstevel@tonic-gate		if (mpcb->mpcb_wstate == WSTATE_USER32) {
9127c478bdstevel@tonic-gate			rw_size = sizeof (struct rwindow32);
9137552190raf			sp = (caddr_t)(uintptr_t)(caddr32_t)r->r_sp;
9147c478bdstevel@tonic-gate			rwp = sp;
9157c478bdstevel@tonic-gate			is64 = 0;
9167c478bdstevel@tonic-gate		} else {
9177c478bdstevel@tonic-gate			rw_size = sizeof (struct rwindow);
9187c478bdstevel@tonic-gate			sp = (caddr_t)r->r_sp;
9197c478bdstevel@tonic-gate			rwp = sp + V9BIAS64;
9207c478bdstevel@tonic-gate			is64 = 1;
9217c478bdstevel@tonic-gate		}
9227c478bdstevel@tonic-gate
9237c478bdstevel@tonic-gate		watched = watch_disable_addr(rwp, rw_size, S_READ);
9247c478bdstevel@tonic-gate		if (is64 &&
9257c478bdstevel@tonic-gate		    copyin(rwp, &lwp->lwp_pcb.pcb_xregs, rw_size) == 0)
9267c478bdstevel@tonic-gate			lwp->lwp_pcb.pcb_xregstat = XREGPRESENT;
9277c478bdstevel@tonic-gate		else if (!is64 &&
9287c478bdstevel@tonic-gate		    copyin(rwp, &rwindow32, rw_size) == 0) {
9297c478bdstevel@tonic-gate			rwindow_32ton(&rwindow32, &lwp->lwp_pcb.pcb_xregs);
9307c478bdstevel@tonic-gate			lwp->lwp_pcb.pcb_xregstat = XREGPRESENT;
9317c478bdstevel@tonic-gate		} else {
9327c478bdstevel@tonic-gate			int i;
9337c478bdstevel@tonic-gate
9347c478bdstevel@tonic-gate			for (i = 0; i < mpcb->mpcb_wbcnt; i++) {
9357c478bdstevel@tonic-gate				if (sp == mpcb->mpcb_spbuf[i]) {
9367c478bdstevel@tonic-gate					if (is64) {
9377c478bdstevel@tonic-gate						bcopy(mpcb->mpcb_wbuf +
9387c478bdstevel@tonic-gate						    (i * rw_size),
9397c478bdstevel@tonic-gate						    &lwp->lwp_pcb.pcb_xregs,
9407c478bdstevel@tonic-gate						    rw_size);
9417c478bdstevel@tonic-gate					} else {
9427c478bdstevel@tonic-gate						struct rwindow32 *rw32 =
9437c478bdstevel@tonic-gate						    (struct rwindow32 *)
9447c478bdstevel@tonic-gate						    (mpcb->mpcb_wbuf +
9457c478bdstevel@tonic-gate						    (i * rw_size));
9467c478bdstevel@tonic-gate						rwindow_32ton(rw32,
9477c478bdstevel@tonic-gate						    &lwp->lwp_pcb.pcb_xregs);
9487c478bdstevel@tonic-gate					}
9497c478bdstevel@tonic-gate					lwp->lwp_pcb.pcb_xregstat = XREGPRESENT;
9507c478bdstevel@tonic-gate					break;
9517c478bdstevel@tonic-gate				}
9527c478bdstevel@tonic-gate			}
9537c478bdstevel@tonic-gate		}
9547c478bdstevel@tonic-gate		if (watched)
9557c478bdstevel@tonic-gate			watch_enable_addr(rwp, rw_size, S_READ);
9567c478bdstevel@tonic-gate	}
9577c478bdstevel@tonic-gate
9587c478bdstevel@tonic-gate	/*
9597c478bdstevel@tonic-gate	 * Make sure the floating point state is saved.
9607c478bdstevel@tonic-gate	 */
9617c478bdstevel@tonic-gate	fp_prsave(pfp);
9627c478bdstevel@tonic-gate
9637c478bdstevel@tonic-gate	if (p->p_model == DATAMODEL_ILP32)
9647552190raf		pc = (caddr_t)(uintptr_t)(caddr32_t)r->r_pc;
9657c478bdstevel@tonic-gate	else
9667c478bdstevel@tonic-gate		pc = (caddr_t)r->r_pc;
9677c478bdstevel@tonic-gate
9687c478bdstevel@tonic-gate	if (copyin_nowatch(pc, &lwp->lwp_pcb.pcb_instr,
9697c478bdstevel@tonic-gate	    sizeof (lwp->lwp_pcb.pcb_instr)) == 0)
9707c478bdstevel@tonic-gate		lwp->lwp_pcb.pcb_flags |= INSTR_VALID;
9717c478bdstevel@tonic-gate	else {
9727c478bdstevel@tonic-gate		lwp->lwp_pcb.pcb_flags &= ~INSTR_VALID;
9737c478bdstevel@tonic-gate		lwp->lwp_pcb.pcb_instr = 0;
9747c478bdstevel@tonic-gate	}
9757c478bdstevel@tonic-gate
9767c478bdstevel@tonic-gate	(void) save_syscall_args();
9778548bf7nr	ASSERT(lwp->lwp_nostop == 1);
9788548bf7nr	lwp->lwp_nostop = 0;
97907a4882Roger A. Faulkner
98007a4882Roger A. Faulkner	lwp->lwp_pcb.pcb_flags |= PRSTOP_CALLED;
98107a4882Roger A. Faulkner	aston(curthread);	/* so prunstop() will be called */
98207a4882Roger A. Faulkner}
98307a4882Roger A. Faulkner
98407a4882Roger A. Faulkner/*
98507a4882Roger A. Faulkner * Inform prstop() that it should do its work again
98607a4882Roger A. Faulkner * the next time it is called.
98707a4882Roger A. Faulkner */
98807a4882Roger A. Faulknervoid
98907a4882Roger A. Faulknerprunstop(void)
99007a4882Roger A. Faulkner{
99107a4882Roger A. Faulkner	ttolwp(curthread)->lwp_pcb.pcb_flags &= ~PRSTOP_CALLED;
9927c478bdstevel@tonic-gate}
9937c478bdstevel@tonic-gate
9947c478bdstevel@tonic-gate/*
9957c478bdstevel@tonic-gate * Fetch the user-level instruction on which the lwp is stopped.
9967c478bdstevel@tonic-gate * It was saved by the lwp itself, in prstop().
9977c478bdstevel@tonic-gate * Return non-zero if the instruction is valid.
9987c478bdstevel@tonic-gate */
9997c478bdstevel@tonic-gateint
10007c478bdstevel@tonic-gateprfetchinstr(klwp_t *lwp, ulong_t *ip)
10017c478bdstevel@tonic-gate{
10027c478bdstevel@tonic-gate	*ip = (ulong_t)(instr_t)lwp->lwp_pcb.pcb_instr;
10037c478bdstevel@tonic-gate	return (lwp->lwp_pcb.pcb_flags & INSTR_VALID);
10047c478bdstevel@tonic-gate}
10057c478bdstevel@tonic-gate
10067c478bdstevel@tonic-gateint
10077c478bdstevel@tonic-gateprnwindows(klwp_t *lwp)
10087c478bdstevel@tonic-gate{
10097c478bdstevel@tonic-gate	struct machpcb *mpcb = lwptompcb(lwp);
10107c478bdstevel@tonic-gate
10117c478bdstevel@tonic-gate	return (mpcb->mpcb_wbcnt);
10127c478bdstevel@tonic-gate}
10137c478bdstevel@tonic-gate
10147c478bdstevel@tonic-gatevoid
10157c478bdstevel@tonic-gateprgetwindows(klwp_t *lwp, gwindows_t *gwp)
10167c478bdstevel@tonic-gate{
10177c478bdstevel@tonic-gate	getgwins(lwp, gwp);
10187c478bdstevel@tonic-gate}
10197c478bdstevel@tonic-gate
10207c478bdstevel@tonic-gate#ifdef	_SYSCALL32_IMPL
10217c478bdstevel@tonic-gatevoid
10227c478bdstevel@tonic-gateprgetwindows32(klwp_t *lwp, gwindows32_t *gwp)
10237c478bdstevel@tonic-gate{
10247c478bdstevel@tonic-gate	getgwins32(lwp, gwp);
10257c478bdstevel@tonic-gate}
10267c478bdstevel@tonic-gate#endif	/* _SYSCALL32_IMPL */
10277c478bdstevel@tonic-gate
10287c478bdstevel@tonic-gate/*
10297c478bdstevel@tonic-gate * Called from trap() when a load or store instruction
10307c478bdstevel@tonic-gate * falls in a watched page but is not a watchpoint.
10317c478bdstevel@tonic-gate * We emulate the instruction in the kernel.
10327c478bdstevel@tonic-gate */
10337c478bdstevel@tonic-gateint
10347c478bdstevel@tonic-gatepr_watch_emul(struct regs *rp, caddr_t addr, enum seg_rw rw)
10357c478bdstevel@tonic-gate{
10367c478bdstevel@tonic-gate	char *badaddr = (caddr_t)(-1);
10377c478bdstevel@tonic-gate	int res;
10387c478bdstevel@tonic-gate	int watched;
10397c478bdstevel@tonic-gate
10407c478bdstevel@tonic-gate	/* prevent recursive calls to pr_watch_emul() */
10417c478bdstevel@tonic-gate	ASSERT(!(curthread->t_flag & T_WATCHPT));
10427c478bdstevel@tonic-gate	curthread->t_flag |= T_WATCHPT;
10437c478bdstevel@tonic-gate
10447c478bdstevel@tonic-gate	watched = watch_disable_addr(addr, 16, rw);
10457c478bdstevel@tonic-gate	res = do_unaligned(rp, &badaddr);
10467c478bdstevel@tonic-gate	if (watched)
10477c478bdstevel@tonic-gate		watch_enable_addr(addr, 16, rw);
10487c478bdstevel@tonic-gate
10497c478bdstevel@tonic-gate	curthread->t_flag &= ~T_WATCHPT;
10507c478bdstevel@tonic-gate	if (res == SIMU_SUCCESS) {
10517c478bdstevel@tonic-gate		rp->r_pc = rp->r_npc;
10527c478bdstevel@tonic-gate		rp->r_npc += 4;
10537c478bdstevel@tonic-gate		return (1);
10547c478bdstevel@tonic-gate	}
10557c478bdstevel@tonic-gate	return (0);
10567c478bdstevel@tonic-gate}
1057