1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 1994-1998,2003 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 30*7c478bd9Sstevel@tonic-gate #include <sys/t_lock.h> 31*7c478bd9Sstevel@tonic-gate #include <sys/klwp.h> 32*7c478bd9Sstevel@tonic-gate #include <sys/ucontext.h> 33*7c478bd9Sstevel@tonic-gate #include <sys/procfs.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/privregs.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/archsystm.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/machsystm.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/fpu/fpusystm.h> 41*7c478bd9Sstevel@tonic-gate 42*7c478bd9Sstevel@tonic-gate /* 43*7c478bd9Sstevel@tonic-gate * Association of extra register state with a struct ucontext is 44*7c478bd9Sstevel@tonic-gate * done by placing an xrs_t within the uc_mcontext filler area. 45*7c478bd9Sstevel@tonic-gate * 46*7c478bd9Sstevel@tonic-gate * The following routines provide an interface for this association. 47*7c478bd9Sstevel@tonic-gate */ 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate /* 50*7c478bd9Sstevel@tonic-gate * clear the struct ucontext extra register state pointer 51*7c478bd9Sstevel@tonic-gate */ 52*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 53*7c478bd9Sstevel@tonic-gate void 54*7c478bd9Sstevel@tonic-gate xregs_clrptr(klwp_id_t lwp, ucontext_t *uc) 55*7c478bd9Sstevel@tonic-gate { 56*7c478bd9Sstevel@tonic-gate uc->uc_mcontext.xrs.xrs_id = 0; 57*7c478bd9Sstevel@tonic-gate uc->uc_mcontext.xrs.xrs_ptr = NULL; 58*7c478bd9Sstevel@tonic-gate } 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate /* 61*7c478bd9Sstevel@tonic-gate * indicate whether or not an extra register state 62*7c478bd9Sstevel@tonic-gate * pointer is associated with a struct ucontext 63*7c478bd9Sstevel@tonic-gate */ 64*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 65*7c478bd9Sstevel@tonic-gate int 66*7c478bd9Sstevel@tonic-gate xregs_hasptr(klwp_id_t lwp, ucontext_t *uc) 67*7c478bd9Sstevel@tonic-gate { 68*7c478bd9Sstevel@tonic-gate return (uc->uc_mcontext.xrs.xrs_id == XRS_ID); 69*7c478bd9Sstevel@tonic-gate } 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate /* 72*7c478bd9Sstevel@tonic-gate * get the struct ucontext extra register state pointer field 73*7c478bd9Sstevel@tonic-gate */ 74*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 75*7c478bd9Sstevel@tonic-gate caddr_t 76*7c478bd9Sstevel@tonic-gate xregs_getptr(klwp_id_t lwp, ucontext_t *uc) 77*7c478bd9Sstevel@tonic-gate { 78*7c478bd9Sstevel@tonic-gate if (uc->uc_mcontext.xrs.xrs_id == XRS_ID) 79*7c478bd9Sstevel@tonic-gate return (uc->uc_mcontext.xrs.xrs_ptr); 80*7c478bd9Sstevel@tonic-gate return (NULL); 81*7c478bd9Sstevel@tonic-gate } 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate /* 84*7c478bd9Sstevel@tonic-gate * set the struct ucontext extra register state pointer field 85*7c478bd9Sstevel@tonic-gate */ 86*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 87*7c478bd9Sstevel@tonic-gate void 88*7c478bd9Sstevel@tonic-gate xregs_setptr(klwp_id_t lwp, ucontext_t *uc, caddr_t xrp) 89*7c478bd9Sstevel@tonic-gate { 90*7c478bd9Sstevel@tonic-gate uc->uc_mcontext.xrs.xrs_id = XRS_ID; 91*7c478bd9Sstevel@tonic-gate uc->uc_mcontext.xrs.xrs_ptr = xrp; 92*7c478bd9Sstevel@tonic-gate } 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 97*7c478bd9Sstevel@tonic-gate void 98*7c478bd9Sstevel@tonic-gate xregs_clrptr32(klwp_id_t lwp, ucontext32_t *uc) 99*7c478bd9Sstevel@tonic-gate { 100*7c478bd9Sstevel@tonic-gate uc->uc_mcontext.xrs.xrs_id = 0; 101*7c478bd9Sstevel@tonic-gate uc->uc_mcontext.xrs.xrs_ptr = 0; 102*7c478bd9Sstevel@tonic-gate } 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 105*7c478bd9Sstevel@tonic-gate int 106*7c478bd9Sstevel@tonic-gate xregs_hasptr32(klwp_id_t lwp, ucontext32_t *uc) 107*7c478bd9Sstevel@tonic-gate { 108*7c478bd9Sstevel@tonic-gate return (uc->uc_mcontext.xrs.xrs_id == XRS_ID); 109*7c478bd9Sstevel@tonic-gate } 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 112*7c478bd9Sstevel@tonic-gate caddr32_t 113*7c478bd9Sstevel@tonic-gate xregs_getptr32(klwp_id_t lwp, ucontext32_t *uc) 114*7c478bd9Sstevel@tonic-gate { 115*7c478bd9Sstevel@tonic-gate if (uc->uc_mcontext.xrs.xrs_id == XRS_ID) 116*7c478bd9Sstevel@tonic-gate return (uc->uc_mcontext.xrs.xrs_ptr); 117*7c478bd9Sstevel@tonic-gate return (0); 118*7c478bd9Sstevel@tonic-gate } 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 121*7c478bd9Sstevel@tonic-gate void 122*7c478bd9Sstevel@tonic-gate xregs_setptr32(klwp_id_t lwp, ucontext32_t *uc, caddr32_t xrp) 123*7c478bd9Sstevel@tonic-gate { 124*7c478bd9Sstevel@tonic-gate uc->uc_mcontext.xrs.xrs_id = XRS_ID; 125*7c478bd9Sstevel@tonic-gate uc->uc_mcontext.xrs.xrs_ptr = xrp; 126*7c478bd9Sstevel@tonic-gate } 127*7c478bd9Sstevel@tonic-gate 128*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate /* 131*7c478bd9Sstevel@tonic-gate * Extra register state manipulation routines. 132*7c478bd9Sstevel@tonic-gate * NOTE: 'lwp' might not correspond to 'curthread' in any of the 133*7c478bd9Sstevel@tonic-gate * functions below since they are called from code in /proc to get 134*7c478bd9Sstevel@tonic-gate * or set the extra registers of another lwp. 135*7c478bd9Sstevel@tonic-gate */ 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate int xregs_exists = 1; 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate #define GET_UPPER_32(all) (uint32_t)((uint64_t)(all) >> 32) 140*7c478bd9Sstevel@tonic-gate #define SET_ALL_64(upper, lower) \ 141*7c478bd9Sstevel@tonic-gate (((uint64_t)(upper) << 32) | (uint32_t)(lower)) 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate /* 145*7c478bd9Sstevel@tonic-gate * fill in the extra register state area specified with the 146*7c478bd9Sstevel@tonic-gate * specified lwp's non-floating-point extra register state 147*7c478bd9Sstevel@tonic-gate * information 148*7c478bd9Sstevel@tonic-gate */ 149*7c478bd9Sstevel@tonic-gate void 150*7c478bd9Sstevel@tonic-gate xregs_getgregs(klwp_id_t lwp, caddr_t xrp) 151*7c478bd9Sstevel@tonic-gate { 152*7c478bd9Sstevel@tonic-gate prxregset_t *xregs = (prxregset_t *)xrp; 153*7c478bd9Sstevel@tonic-gate struct regs *rp = lwptoregs(lwp); 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate if (xregs == NULL) 156*7c478bd9Sstevel@tonic-gate return; 157*7c478bd9Sstevel@tonic-gate 158*7c478bd9Sstevel@tonic-gate xregs->pr_type = XR_TYPE_V8P; 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate xregs->pr_un.pr_v8p.pr_xg[XR_G0] = 0; 161*7c478bd9Sstevel@tonic-gate xregs->pr_un.pr_v8p.pr_xg[XR_G1] = GET_UPPER_32(rp->r_g1); 162*7c478bd9Sstevel@tonic-gate xregs->pr_un.pr_v8p.pr_xg[XR_G2] = GET_UPPER_32(rp->r_g2); 163*7c478bd9Sstevel@tonic-gate xregs->pr_un.pr_v8p.pr_xg[XR_G3] = GET_UPPER_32(rp->r_g3); 164*7c478bd9Sstevel@tonic-gate xregs->pr_un.pr_v8p.pr_xg[XR_G4] = GET_UPPER_32(rp->r_g4); 165*7c478bd9Sstevel@tonic-gate xregs->pr_un.pr_v8p.pr_xg[XR_G5] = GET_UPPER_32(rp->r_g5); 166*7c478bd9Sstevel@tonic-gate xregs->pr_un.pr_v8p.pr_xg[XR_G6] = GET_UPPER_32(rp->r_g6); 167*7c478bd9Sstevel@tonic-gate xregs->pr_un.pr_v8p.pr_xg[XR_G7] = GET_UPPER_32(rp->r_g7); 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate xregs->pr_un.pr_v8p.pr_xo[XR_O0] = GET_UPPER_32(rp->r_o0); 170*7c478bd9Sstevel@tonic-gate xregs->pr_un.pr_v8p.pr_xo[XR_O1] = GET_UPPER_32(rp->r_o1); 171*7c478bd9Sstevel@tonic-gate xregs->pr_un.pr_v8p.pr_xo[XR_O2] = GET_UPPER_32(rp->r_o2); 172*7c478bd9Sstevel@tonic-gate xregs->pr_un.pr_v8p.pr_xo[XR_O3] = GET_UPPER_32(rp->r_o3); 173*7c478bd9Sstevel@tonic-gate xregs->pr_un.pr_v8p.pr_xo[XR_O4] = GET_UPPER_32(rp->r_o4); 174*7c478bd9Sstevel@tonic-gate xregs->pr_un.pr_v8p.pr_xo[XR_O5] = GET_UPPER_32(rp->r_o5); 175*7c478bd9Sstevel@tonic-gate xregs->pr_un.pr_v8p.pr_xo[XR_O6] = GET_UPPER_32(rp->r_o6); 176*7c478bd9Sstevel@tonic-gate xregs->pr_un.pr_v8p.pr_xo[XR_O7] = GET_UPPER_32(rp->r_o7); 177*7c478bd9Sstevel@tonic-gate 178*7c478bd9Sstevel@tonic-gate xregs->pr_un.pr_v8p.pr_tstate = rp->r_tstate; 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate xregs_getgfiller(lwp, xrp); 181*7c478bd9Sstevel@tonic-gate } 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate /* 184*7c478bd9Sstevel@tonic-gate * fill in the extra register state area specified with the 185*7c478bd9Sstevel@tonic-gate * specified lwp's floating-point extra register state information 186*7c478bd9Sstevel@tonic-gate */ 187*7c478bd9Sstevel@tonic-gate void 188*7c478bd9Sstevel@tonic-gate xregs_getfpregs(klwp_id_t lwp, caddr_t xrp) 189*7c478bd9Sstevel@tonic-gate { 190*7c478bd9Sstevel@tonic-gate prxregset_t *xregs = (prxregset_t *)xrp; 191*7c478bd9Sstevel@tonic-gate kfpu_t *fp = lwptofpu(lwp); 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate if (xregs == NULL) 194*7c478bd9Sstevel@tonic-gate return; 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate kpreempt_disable(); 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate xregs->pr_type = XR_TYPE_V8P; 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate if (ttolwp(curthread) == lwp) 201*7c478bd9Sstevel@tonic-gate fp->fpu_fprs = _fp_read_fprs(); 202*7c478bd9Sstevel@tonic-gate if ((fp->fpu_en) || (fp->fpu_fprs & FPRS_FEF)) { 203*7c478bd9Sstevel@tonic-gate /* 204*7c478bd9Sstevel@tonic-gate * If we have an fpu and the current thread owns the fp 205*7c478bd9Sstevel@tonic-gate * context, flush fp registers into the pcb. 206*7c478bd9Sstevel@tonic-gate */ 207*7c478bd9Sstevel@tonic-gate if (fpu_exists && (ttolwp(curthread) == lwp)) { 208*7c478bd9Sstevel@tonic-gate if ((fp->fpu_fprs & FPRS_FEF) != FPRS_FEF) { 209*7c478bd9Sstevel@tonic-gate uint32_t fprs = (FPRS_FEF|FPRS_DU|FPRS_DL); 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate _fp_write_fprs(fprs); 212*7c478bd9Sstevel@tonic-gate fp->fpu_fprs = fprs; 213*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 214*7c478bd9Sstevel@tonic-gate if (fpdispr) { 215*7c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "xregs_getfpregs " 216*7c478bd9Sstevel@tonic-gate "with fp disabled!"); 217*7c478bd9Sstevel@tonic-gate } 218*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 219*7c478bd9Sstevel@tonic-gate } 220*7c478bd9Sstevel@tonic-gate fp_v8p_fksave(fp); 221*7c478bd9Sstevel@tonic-gate } 222*7c478bd9Sstevel@tonic-gate (void) kcopy(&fp->fpu_fr.fpu_dregs[16], 223*7c478bd9Sstevel@tonic-gate &xregs->pr_un.pr_v8p.pr_xfr, 224*7c478bd9Sstevel@tonic-gate sizeof (xregs->pr_un.pr_v8p.pr_xfr)); 225*7c478bd9Sstevel@tonic-gate xregs->pr_un.pr_v8p.pr_xfsr = GET_UPPER_32(fp->fpu_fsr); 226*7c478bd9Sstevel@tonic-gate xregs->pr_un.pr_v8p.pr_fprs = fp->fpu_fprs; 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate xregs_getfpfiller(lwp, xrp); 229*7c478bd9Sstevel@tonic-gate } else { 230*7c478bd9Sstevel@tonic-gate int i; 231*7c478bd9Sstevel@tonic-gate for (i = 0; i < 32; i++) /* Nan */ 232*7c478bd9Sstevel@tonic-gate xregs->pr_un.pr_v8p.pr_xfr.pr_regs[i] = (uint32_t)-1; 233*7c478bd9Sstevel@tonic-gate } 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate kpreempt_enable(); 236*7c478bd9Sstevel@tonic-gate } 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate /* 239*7c478bd9Sstevel@tonic-gate * fill in the extra register state area specified with 240*7c478bd9Sstevel@tonic-gate * the specified lwp's extra register state information 241*7c478bd9Sstevel@tonic-gate */ 242*7c478bd9Sstevel@tonic-gate void 243*7c478bd9Sstevel@tonic-gate xregs_get(klwp_id_t lwp, caddr_t xrp) 244*7c478bd9Sstevel@tonic-gate { 245*7c478bd9Sstevel@tonic-gate if (xrp != NULL) { 246*7c478bd9Sstevel@tonic-gate bzero(xrp, sizeof (prxregset_t)); 247*7c478bd9Sstevel@tonic-gate xregs_getgregs(lwp, xrp); 248*7c478bd9Sstevel@tonic-gate xregs_getfpregs(lwp, xrp); 249*7c478bd9Sstevel@tonic-gate } 250*7c478bd9Sstevel@tonic-gate } 251*7c478bd9Sstevel@tonic-gate 252*7c478bd9Sstevel@tonic-gate /* 253*7c478bd9Sstevel@tonic-gate * set the specified lwp's non-floating-point extra 254*7c478bd9Sstevel@tonic-gate * register state based on the specified input 255*7c478bd9Sstevel@tonic-gate */ 256*7c478bd9Sstevel@tonic-gate void 257*7c478bd9Sstevel@tonic-gate xregs_setgregs(klwp_id_t lwp, caddr_t xrp) 258*7c478bd9Sstevel@tonic-gate { 259*7c478bd9Sstevel@tonic-gate prxregset_t *xregs = (prxregset_t *)xrp; 260*7c478bd9Sstevel@tonic-gate struct regs *rp = lwptoregs(lwp); 261*7c478bd9Sstevel@tonic-gate int current = (lwp == curthread->t_lwp); 262*7c478bd9Sstevel@tonic-gate 263*7c478bd9Sstevel@tonic-gate if (xregs == NULL) 264*7c478bd9Sstevel@tonic-gate return; 265*7c478bd9Sstevel@tonic-gate 266*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 267*7c478bd9Sstevel@tonic-gate if (xregs->pr_type != XR_TYPE_V8P) { 268*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 269*7c478bd9Sstevel@tonic-gate "xregs_setgregs: pr_type is %d and should be %d", 270*7c478bd9Sstevel@tonic-gate xregs->pr_type, XR_TYPE_V8P); 271*7c478bd9Sstevel@tonic-gate } 272*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 273*7c478bd9Sstevel@tonic-gate 274*7c478bd9Sstevel@tonic-gate if (current) { 275*7c478bd9Sstevel@tonic-gate /* 276*7c478bd9Sstevel@tonic-gate * copy the args from the regs first 277*7c478bd9Sstevel@tonic-gate */ 278*7c478bd9Sstevel@tonic-gate (void) save_syscall_args(); 279*7c478bd9Sstevel@tonic-gate } 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate rp->r_g1 = SET_ALL_64(xregs->pr_un.pr_v8p.pr_xg[XR_G1], rp->r_g1); 282*7c478bd9Sstevel@tonic-gate rp->r_g2 = SET_ALL_64(xregs->pr_un.pr_v8p.pr_xg[XR_G2], rp->r_g2); 283*7c478bd9Sstevel@tonic-gate rp->r_g3 = SET_ALL_64(xregs->pr_un.pr_v8p.pr_xg[XR_G3], rp->r_g3); 284*7c478bd9Sstevel@tonic-gate rp->r_g4 = SET_ALL_64(xregs->pr_un.pr_v8p.pr_xg[XR_G4], rp->r_g4); 285*7c478bd9Sstevel@tonic-gate rp->r_g5 = SET_ALL_64(xregs->pr_un.pr_v8p.pr_xg[XR_G5], rp->r_g5); 286*7c478bd9Sstevel@tonic-gate rp->r_g6 = SET_ALL_64(xregs->pr_un.pr_v8p.pr_xg[XR_G6], rp->r_g6); 287*7c478bd9Sstevel@tonic-gate rp->r_g7 = SET_ALL_64(xregs->pr_un.pr_v8p.pr_xg[XR_G7], rp->r_g7); 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate rp->r_o0 = SET_ALL_64(xregs->pr_un.pr_v8p.pr_xo[XR_O0], rp->r_o0); 290*7c478bd9Sstevel@tonic-gate rp->r_o1 = SET_ALL_64(xregs->pr_un.pr_v8p.pr_xo[XR_O1], rp->r_o1); 291*7c478bd9Sstevel@tonic-gate rp->r_o2 = SET_ALL_64(xregs->pr_un.pr_v8p.pr_xo[XR_O2], rp->r_o2); 292*7c478bd9Sstevel@tonic-gate rp->r_o3 = SET_ALL_64(xregs->pr_un.pr_v8p.pr_xo[XR_O3], rp->r_o3); 293*7c478bd9Sstevel@tonic-gate rp->r_o4 = SET_ALL_64(xregs->pr_un.pr_v8p.pr_xo[XR_O4], rp->r_o4); 294*7c478bd9Sstevel@tonic-gate rp->r_o5 = SET_ALL_64(xregs->pr_un.pr_v8p.pr_xo[XR_O5], rp->r_o5); 295*7c478bd9Sstevel@tonic-gate rp->r_o6 = SET_ALL_64(xregs->pr_un.pr_v8p.pr_xo[XR_O6], rp->r_o6); 296*7c478bd9Sstevel@tonic-gate rp->r_o7 = SET_ALL_64(xregs->pr_un.pr_v8p.pr_xo[XR_O7], rp->r_o7); 297*7c478bd9Sstevel@tonic-gate 298*7c478bd9Sstevel@tonic-gate rp->r_tstate &= ~((uint64_t)CCR_XCC << TSTATE_CCR_SHIFT); 299*7c478bd9Sstevel@tonic-gate rp->r_tstate |= xregs->pr_un.pr_v8p.pr_tstate & 300*7c478bd9Sstevel@tonic-gate ((uint64_t)CCR_XCC << TSTATE_CCR_SHIFT); 301*7c478bd9Sstevel@tonic-gate rp->r_tstate &= ~((uint64_t)TSTATE_ASI_MASK << TSTATE_ASI_SHIFT); 302*7c478bd9Sstevel@tonic-gate rp->r_tstate |= xregs->pr_un.pr_v8p.pr_tstate & 303*7c478bd9Sstevel@tonic-gate ((uint64_t)TSTATE_ASI_MASK << TSTATE_ASI_SHIFT); 304*7c478bd9Sstevel@tonic-gate 305*7c478bd9Sstevel@tonic-gate xregs_setgfiller(lwp, xrp); 306*7c478bd9Sstevel@tonic-gate 307*7c478bd9Sstevel@tonic-gate if (current) { 308*7c478bd9Sstevel@tonic-gate /* 309*7c478bd9Sstevel@tonic-gate * This was called from a system call, but we 310*7c478bd9Sstevel@tonic-gate * do not want to return via the shared window; 311*7c478bd9Sstevel@tonic-gate * restoring the CPU context changes everything. 312*7c478bd9Sstevel@tonic-gate */ 313*7c478bd9Sstevel@tonic-gate lwp->lwp_eosys = JUSTRETURN; 314*7c478bd9Sstevel@tonic-gate curthread->t_post_sys = 1; 315*7c478bd9Sstevel@tonic-gate } 316*7c478bd9Sstevel@tonic-gate } 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate /* 319*7c478bd9Sstevel@tonic-gate * set the specified lwp's floating-point extra 320*7c478bd9Sstevel@tonic-gate * register state based on the specified input 321*7c478bd9Sstevel@tonic-gate */ 322*7c478bd9Sstevel@tonic-gate void 323*7c478bd9Sstevel@tonic-gate xregs_setfpregs(klwp_id_t lwp, caddr_t xrp) 324*7c478bd9Sstevel@tonic-gate { 325*7c478bd9Sstevel@tonic-gate prxregset_t *xregs = (prxregset_t *)xrp; 326*7c478bd9Sstevel@tonic-gate kfpu_t *fp = lwptofpu(lwp); 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate if (xregs == NULL) 329*7c478bd9Sstevel@tonic-gate return; 330*7c478bd9Sstevel@tonic-gate 331*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 332*7c478bd9Sstevel@tonic-gate if (xregs->pr_type != XR_TYPE_V8P) { 333*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 334*7c478bd9Sstevel@tonic-gate "xregs_setfpregs: pr_type is %d and should be %d", 335*7c478bd9Sstevel@tonic-gate xregs->pr_type, XR_TYPE_V8P); 336*7c478bd9Sstevel@tonic-gate } 337*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 338*7c478bd9Sstevel@tonic-gate if ((fp->fpu_en) || (xregs->pr_un.pr_v8p.pr_fprs & FPRS_FEF)) { 339*7c478bd9Sstevel@tonic-gate kpreempt_disable(); 340*7c478bd9Sstevel@tonic-gate (void) kcopy(&xregs->pr_un.pr_v8p.pr_xfr, 341*7c478bd9Sstevel@tonic-gate &fp->fpu_fr.fpu_dregs[16], 342*7c478bd9Sstevel@tonic-gate sizeof (xregs->pr_un.pr_v8p.pr_xfr)); 343*7c478bd9Sstevel@tonic-gate fp->fpu_fprs = xregs->pr_un.pr_v8p.pr_fprs; 344*7c478bd9Sstevel@tonic-gate fp->fpu_fsr = SET_ALL_64(xregs->pr_un.pr_v8p.pr_xfsr, 345*7c478bd9Sstevel@tonic-gate fp->fpu_fsr); 346*7c478bd9Sstevel@tonic-gate 347*7c478bd9Sstevel@tonic-gate xregs_setfpfiller(lwp, xrp); 348*7c478bd9Sstevel@tonic-gate 349*7c478bd9Sstevel@tonic-gate /* 350*7c478bd9Sstevel@tonic-gate * If not the current lwp then resume() will handle it 351*7c478bd9Sstevel@tonic-gate */ 352*7c478bd9Sstevel@tonic-gate if (lwp != ttolwp(curthread)) { 353*7c478bd9Sstevel@tonic-gate /* force resume to reload fp regs */ 354*7c478bd9Sstevel@tonic-gate kpreempt_enable(); 355*7c478bd9Sstevel@tonic-gate return; 356*7c478bd9Sstevel@tonic-gate } 357*7c478bd9Sstevel@tonic-gate 358*7c478bd9Sstevel@tonic-gate if (fpu_exists) { 359*7c478bd9Sstevel@tonic-gate fp->fpu_fprs = _fp_read_fprs(); 360*7c478bd9Sstevel@tonic-gate if ((fp->fpu_fprs & FPRS_FEF) != FPRS_FEF) { 361*7c478bd9Sstevel@tonic-gate uint32_t fprs = (FPRS_FEF|FPRS_DU|FPRS_DL); 362*7c478bd9Sstevel@tonic-gate 363*7c478bd9Sstevel@tonic-gate _fp_write_fprs(fprs); 364*7c478bd9Sstevel@tonic-gate fp->fpu_fprs = (V9_FPU_FPRS_TYPE)fprs; 365*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 366*7c478bd9Sstevel@tonic-gate if (fpdispr) { 367*7c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "xregs_setfpregs " 368*7c478bd9Sstevel@tonic-gate "with fp disabled!"); 369*7c478bd9Sstevel@tonic-gate } 370*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 371*7c478bd9Sstevel@tonic-gate } 372*7c478bd9Sstevel@tonic-gate fp_v8p_load(fp); 373*7c478bd9Sstevel@tonic-gate } 374*7c478bd9Sstevel@tonic-gate 375*7c478bd9Sstevel@tonic-gate kpreempt_enable(); 376*7c478bd9Sstevel@tonic-gate } 377*7c478bd9Sstevel@tonic-gate } 378*7c478bd9Sstevel@tonic-gate 379*7c478bd9Sstevel@tonic-gate /* 380*7c478bd9Sstevel@tonic-gate * set the specified lwp's extra register 381*7c478bd9Sstevel@tonic-gate * state based on the specified input 382*7c478bd9Sstevel@tonic-gate */ 383*7c478bd9Sstevel@tonic-gate void 384*7c478bd9Sstevel@tonic-gate xregs_set(klwp_id_t lwp, caddr_t xrp) 385*7c478bd9Sstevel@tonic-gate { 386*7c478bd9Sstevel@tonic-gate if (xrp != NULL) { 387*7c478bd9Sstevel@tonic-gate xregs_setgregs(lwp, xrp); 388*7c478bd9Sstevel@tonic-gate xregs_setfpregs(lwp, xrp); 389*7c478bd9Sstevel@tonic-gate } 390*7c478bd9Sstevel@tonic-gate } 391*7c478bd9Sstevel@tonic-gate 392*7c478bd9Sstevel@tonic-gate /* 393*7c478bd9Sstevel@tonic-gate * return the size of the extra register state 394*7c478bd9Sstevel@tonic-gate */ 395*7c478bd9Sstevel@tonic-gate int 396*7c478bd9Sstevel@tonic-gate xregs_getsize(proc_t *p) 397*7c478bd9Sstevel@tonic-gate { 398*7c478bd9Sstevel@tonic-gate if (!xregs_exists || p->p_model == DATAMODEL_LP64) 399*7c478bd9Sstevel@tonic-gate return (0); 400*7c478bd9Sstevel@tonic-gate return (sizeof (prxregset_t)); 401*7c478bd9Sstevel@tonic-gate } 402