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