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 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 24*7c478bd9Sstevel@tonic-gate 25*7c478bd9Sstevel@tonic-gate 26*7c478bd9Sstevel@tonic-gate /* 27*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 28*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 29*7c478bd9Sstevel@tonic-gate */ 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/vmparam.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/stack.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/frame.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/proc.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/ucontext.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/asm_linkage.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/bootconf.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/archsystm.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/fpu/fpusystm.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/privregs.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/machpcb.h> 51*7c478bd9Sstevel@tonic-gate #include <sys/psr_compat.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 53*7c478bd9Sstevel@tonic-gate #include <sys/asi.h> 54*7c478bd9Sstevel@tonic-gate #include <sys/copyops.h> 55*7c478bd9Sstevel@tonic-gate #include <sys/model.h> 56*7c478bd9Sstevel@tonic-gate #include <sys/panic.h> 57*7c478bd9Sstevel@tonic-gate #include <sys/exec.h> 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate /* 60*7c478bd9Sstevel@tonic-gate * modify the lower 32bits of a uint64_t 61*7c478bd9Sstevel@tonic-gate */ 62*7c478bd9Sstevel@tonic-gate #define SET_LOWER_32(all, lower) \ 63*7c478bd9Sstevel@tonic-gate (((uint64_t)(all) & 0xffffffff00000000) | (uint32_t)(lower)) 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate #define MEMCPY_FPU_EN 2 /* fprs on and fpu_en == 0 */ 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate static uint_t mkpsr(uint64_t tstate, uint32_t fprs); 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 70*7c478bd9Sstevel@tonic-gate static void fpuregset_32ton(const fpregset32_t *src, fpregset_t *dest, 71*7c478bd9Sstevel@tonic-gate const struct fq32 *sfq, struct fq *dfq); 72*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate /* 75*7c478bd9Sstevel@tonic-gate * Set floating-point registers. 76*7c478bd9Sstevel@tonic-gate * NOTE: 'lwp' might not correspond to 'curthread' since this is 77*7c478bd9Sstevel@tonic-gate * called from code in /proc to set the registers of another lwp. 78*7c478bd9Sstevel@tonic-gate */ 79*7c478bd9Sstevel@tonic-gate void 80*7c478bd9Sstevel@tonic-gate setfpregs(klwp_t *lwp, fpregset_t *fp) 81*7c478bd9Sstevel@tonic-gate { 82*7c478bd9Sstevel@tonic-gate struct machpcb *mpcb; 83*7c478bd9Sstevel@tonic-gate kfpu_t *pfp; 84*7c478bd9Sstevel@tonic-gate uint32_t fprs = (FPRS_FEF|FPRS_DU|FPRS_DL); 85*7c478bd9Sstevel@tonic-gate model_t model = lwp_getdatamodel(lwp); 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate mpcb = lwptompcb(lwp); 88*7c478bd9Sstevel@tonic-gate pfp = lwptofpu(lwp); 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate /* 91*7c478bd9Sstevel@tonic-gate * This is always true for both "real" fp programs and memcpy fp 92*7c478bd9Sstevel@tonic-gate * programs, because we force fpu_en to MEMCPY_FPU_EN in getfpregs, 93*7c478bd9Sstevel@tonic-gate * for the memcpy and threads cases where (fpu_en == 0) && 94*7c478bd9Sstevel@tonic-gate * (fpu_fprs & FPRS_FEF), if setfpregs is called after getfpregs. 95*7c478bd9Sstevel@tonic-gate */ 96*7c478bd9Sstevel@tonic-gate if (fp->fpu_en) { 97*7c478bd9Sstevel@tonic-gate kpreempt_disable(); 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate if (!(pfp->fpu_en) && (!(pfp->fpu_fprs & FPRS_FEF)) && 100*7c478bd9Sstevel@tonic-gate fpu_exists) { 101*7c478bd9Sstevel@tonic-gate /* 102*7c478bd9Sstevel@tonic-gate * He's not currently using the FPU but wants to in his 103*7c478bd9Sstevel@tonic-gate * new context - arrange for this on return to userland. 104*7c478bd9Sstevel@tonic-gate */ 105*7c478bd9Sstevel@tonic-gate pfp->fpu_fprs = (uint32_t)fprs; 106*7c478bd9Sstevel@tonic-gate } 107*7c478bd9Sstevel@tonic-gate /* 108*7c478bd9Sstevel@tonic-gate * Get setfpregs to restore fpu_en to zero 109*7c478bd9Sstevel@tonic-gate * for the memcpy/threads case (where pfp->fpu_en == 0 && 110*7c478bd9Sstevel@tonic-gate * (pfp->fp_fprs & FPRS_FEF) == FPRS_FEF). 111*7c478bd9Sstevel@tonic-gate */ 112*7c478bd9Sstevel@tonic-gate if (fp->fpu_en == MEMCPY_FPU_EN) 113*7c478bd9Sstevel@tonic-gate fp->fpu_en = 0; 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate /* 116*7c478bd9Sstevel@tonic-gate * Load up a user's floating point context. 117*7c478bd9Sstevel@tonic-gate */ 118*7c478bd9Sstevel@tonic-gate if (fp->fpu_qcnt > MAXFPQ) /* plug security holes */ 119*7c478bd9Sstevel@tonic-gate fp->fpu_qcnt = MAXFPQ; 120*7c478bd9Sstevel@tonic-gate fp->fpu_q_entrysize = sizeof (struct fq); 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate /* 123*7c478bd9Sstevel@tonic-gate * For v9 kernel, copy all of the fp regs. 124*7c478bd9Sstevel@tonic-gate * For v8 kernel, copy v8 fp regs (lower half of v9 fp regs). 125*7c478bd9Sstevel@tonic-gate * Restore entire fsr for v9, only lower half for v8. 126*7c478bd9Sstevel@tonic-gate */ 127*7c478bd9Sstevel@tonic-gate (void) kcopy(fp, pfp, sizeof (fp->fpu_fr)); 128*7c478bd9Sstevel@tonic-gate if (model == DATAMODEL_LP64) 129*7c478bd9Sstevel@tonic-gate pfp->fpu_fsr = fp->fpu_fsr; 130*7c478bd9Sstevel@tonic-gate else 131*7c478bd9Sstevel@tonic-gate pfp->fpu_fsr = SET_LOWER_32(pfp->fpu_fsr, fp->fpu_fsr); 132*7c478bd9Sstevel@tonic-gate pfp->fpu_qcnt = fp->fpu_qcnt; 133*7c478bd9Sstevel@tonic-gate pfp->fpu_q_entrysize = fp->fpu_q_entrysize; 134*7c478bd9Sstevel@tonic-gate pfp->fpu_en = fp->fpu_en; 135*7c478bd9Sstevel@tonic-gate pfp->fpu_q = mpcb->mpcb_fpu_q; 136*7c478bd9Sstevel@tonic-gate if (fp->fpu_qcnt) 137*7c478bd9Sstevel@tonic-gate (void) kcopy(fp->fpu_q, pfp->fpu_q, 138*7c478bd9Sstevel@tonic-gate fp->fpu_qcnt * fp->fpu_q_entrysize); 139*7c478bd9Sstevel@tonic-gate /* FSR ignores these bits on load, so they can not be set */ 140*7c478bd9Sstevel@tonic-gate pfp->fpu_fsr &= ~(FSR_QNE|FSR_FTT); 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate /* 143*7c478bd9Sstevel@tonic-gate * If not the current process then resume() will handle it. 144*7c478bd9Sstevel@tonic-gate */ 145*7c478bd9Sstevel@tonic-gate if (lwp != ttolwp(curthread)) { 146*7c478bd9Sstevel@tonic-gate /* force resume to reload fp regs */ 147*7c478bd9Sstevel@tonic-gate pfp->fpu_fprs |= FPRS_FEF; 148*7c478bd9Sstevel@tonic-gate kpreempt_enable(); 149*7c478bd9Sstevel@tonic-gate return; 150*7c478bd9Sstevel@tonic-gate } 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate /* 153*7c478bd9Sstevel@tonic-gate * Load up FPU with new floating point context. 154*7c478bd9Sstevel@tonic-gate */ 155*7c478bd9Sstevel@tonic-gate if (fpu_exists) { 156*7c478bd9Sstevel@tonic-gate pfp->fpu_fprs = _fp_read_fprs(); 157*7c478bd9Sstevel@tonic-gate if ((pfp->fpu_fprs & FPRS_FEF) != FPRS_FEF) { 158*7c478bd9Sstevel@tonic-gate _fp_write_fprs(fprs); 159*7c478bd9Sstevel@tonic-gate pfp->fpu_fprs = (uint32_t)fprs; 160*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 161*7c478bd9Sstevel@tonic-gate if (fpdispr) 162*7c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, 163*7c478bd9Sstevel@tonic-gate "setfpregs with fp disabled!\n"); 164*7c478bd9Sstevel@tonic-gate #endif 165*7c478bd9Sstevel@tonic-gate } 166*7c478bd9Sstevel@tonic-gate /* 167*7c478bd9Sstevel@tonic-gate * Load all fp regs for v9 user programs, but only 168*7c478bd9Sstevel@tonic-gate * load the lower half for v8[plus] programs. 169*7c478bd9Sstevel@tonic-gate */ 170*7c478bd9Sstevel@tonic-gate if (model == DATAMODEL_LP64) 171*7c478bd9Sstevel@tonic-gate fp_restore(pfp); 172*7c478bd9Sstevel@tonic-gate else 173*7c478bd9Sstevel@tonic-gate fp_v8_load(pfp); 174*7c478bd9Sstevel@tonic-gate } 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate kpreempt_enable(); 177*7c478bd9Sstevel@tonic-gate } else { 178*7c478bd9Sstevel@tonic-gate if ((pfp->fpu_en) || /* normal fp case */ 179*7c478bd9Sstevel@tonic-gate (pfp->fpu_fprs & FPRS_FEF)) { /* memcpy/threads case */ 180*7c478bd9Sstevel@tonic-gate /* 181*7c478bd9Sstevel@tonic-gate * Currently the lwp has floating point enabled. 182*7c478bd9Sstevel@tonic-gate * Turn off FPRS_FEF in user's fprs, saved and 183*7c478bd9Sstevel@tonic-gate * real copies thereof. 184*7c478bd9Sstevel@tonic-gate */ 185*7c478bd9Sstevel@tonic-gate pfp->fpu_en = 0; 186*7c478bd9Sstevel@tonic-gate if (fpu_exists) { 187*7c478bd9Sstevel@tonic-gate fprs = 0; 188*7c478bd9Sstevel@tonic-gate if (lwp == ttolwp(curthread)) 189*7c478bd9Sstevel@tonic-gate _fp_write_fprs(fprs); 190*7c478bd9Sstevel@tonic-gate pfp->fpu_fprs = (uint32_t)fprs; 191*7c478bd9Sstevel@tonic-gate } 192*7c478bd9Sstevel@tonic-gate } 193*7c478bd9Sstevel@tonic-gate } 194*7c478bd9Sstevel@tonic-gate } 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 197*7c478bd9Sstevel@tonic-gate void 198*7c478bd9Sstevel@tonic-gate setfpregs32(klwp_t *lwp, fpregset32_t *fp) 199*7c478bd9Sstevel@tonic-gate { 200*7c478bd9Sstevel@tonic-gate fpregset_t fpregs; 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate fpuregset_32ton(fp, &fpregs, NULL, NULL); 203*7c478bd9Sstevel@tonic-gate setfpregs(lwp, &fpregs); 204*7c478bd9Sstevel@tonic-gate } 205*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate /* 208*7c478bd9Sstevel@tonic-gate * NOTE: 'lwp' might not correspond to 'curthread' since this is 209*7c478bd9Sstevel@tonic-gate * called from code in /proc to set the registers of another lwp. 210*7c478bd9Sstevel@tonic-gate */ 211*7c478bd9Sstevel@tonic-gate void 212*7c478bd9Sstevel@tonic-gate run_fpq(klwp_t *lwp, fpregset_t *fp) 213*7c478bd9Sstevel@tonic-gate { 214*7c478bd9Sstevel@tonic-gate /* 215*7c478bd9Sstevel@tonic-gate * If the context being loaded up includes a floating queue, 216*7c478bd9Sstevel@tonic-gate * we need to simulate those instructions (since we can't reload 217*7c478bd9Sstevel@tonic-gate * the fpu) and pass the process any appropriate signals 218*7c478bd9Sstevel@tonic-gate */ 219*7c478bd9Sstevel@tonic-gate 220*7c478bd9Sstevel@tonic-gate if (lwp == ttolwp(curthread)) { 221*7c478bd9Sstevel@tonic-gate if (fpu_exists) { 222*7c478bd9Sstevel@tonic-gate if (fp->fpu_qcnt) 223*7c478bd9Sstevel@tonic-gate fp_runq(lwp->lwp_regs); 224*7c478bd9Sstevel@tonic-gate } 225*7c478bd9Sstevel@tonic-gate } 226*7c478bd9Sstevel@tonic-gate } 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate /* 229*7c478bd9Sstevel@tonic-gate * Get floating-point registers. 230*7c478bd9Sstevel@tonic-gate * NOTE: 'lwp' might not correspond to 'curthread' since this is 231*7c478bd9Sstevel@tonic-gate * called from code in /proc to set the registers of another lwp. 232*7c478bd9Sstevel@tonic-gate */ 233*7c478bd9Sstevel@tonic-gate void 234*7c478bd9Sstevel@tonic-gate getfpregs(klwp_t *lwp, fpregset_t *fp) 235*7c478bd9Sstevel@tonic-gate { 236*7c478bd9Sstevel@tonic-gate kfpu_t *pfp; 237*7c478bd9Sstevel@tonic-gate model_t model = lwp_getdatamodel(lwp); 238*7c478bd9Sstevel@tonic-gate 239*7c478bd9Sstevel@tonic-gate pfp = lwptofpu(lwp); 240*7c478bd9Sstevel@tonic-gate kpreempt_disable(); 241*7c478bd9Sstevel@tonic-gate if (fpu_exists && ttolwp(curthread) == lwp) 242*7c478bd9Sstevel@tonic-gate pfp->fpu_fprs = _fp_read_fprs(); 243*7c478bd9Sstevel@tonic-gate 244*7c478bd9Sstevel@tonic-gate /* 245*7c478bd9Sstevel@tonic-gate * First check the fpu_en case, for normal fp programs. 246*7c478bd9Sstevel@tonic-gate * Next check the fprs case, for fp use by memcpy/threads. 247*7c478bd9Sstevel@tonic-gate */ 248*7c478bd9Sstevel@tonic-gate if (((fp->fpu_en = pfp->fpu_en) != 0) || 249*7c478bd9Sstevel@tonic-gate (pfp->fpu_fprs & FPRS_FEF)) { 250*7c478bd9Sstevel@tonic-gate /* 251*7c478bd9Sstevel@tonic-gate * Force setfpregs to restore the fp context in 252*7c478bd9Sstevel@tonic-gate * setfpregs for the memcpy and threads cases (where 253*7c478bd9Sstevel@tonic-gate * pfp->fpu_en == 0 && (pfp->fp_fprs & FPRS_FEF) == FPRS_FEF). 254*7c478bd9Sstevel@tonic-gate */ 255*7c478bd9Sstevel@tonic-gate if (pfp->fpu_en == 0) 256*7c478bd9Sstevel@tonic-gate fp->fpu_en = MEMCPY_FPU_EN; 257*7c478bd9Sstevel@tonic-gate /* 258*7c478bd9Sstevel@tonic-gate * If we have an fpu and the current thread owns the fp 259*7c478bd9Sstevel@tonic-gate * context, flush fp * registers into the pcb. Save all 260*7c478bd9Sstevel@tonic-gate * the fp regs for v9, xregs_getfpregs saves the upper half 261*7c478bd9Sstevel@tonic-gate * for v8plus. Save entire fsr for v9, only lower half for v8. 262*7c478bd9Sstevel@tonic-gate */ 263*7c478bd9Sstevel@tonic-gate if (fpu_exists && ttolwp(curthread) == lwp) { 264*7c478bd9Sstevel@tonic-gate if ((pfp->fpu_fprs & FPRS_FEF) != FPRS_FEF) { 265*7c478bd9Sstevel@tonic-gate uint32_t fprs = (FPRS_FEF|FPRS_DU|FPRS_DL); 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate _fp_write_fprs(fprs); 268*7c478bd9Sstevel@tonic-gate pfp->fpu_fprs = fprs; 269*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 270*7c478bd9Sstevel@tonic-gate if (fpdispr) 271*7c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, 272*7c478bd9Sstevel@tonic-gate "getfpregs with fp disabled!\n"); 273*7c478bd9Sstevel@tonic-gate #endif 274*7c478bd9Sstevel@tonic-gate } 275*7c478bd9Sstevel@tonic-gate if (model == DATAMODEL_LP64) 276*7c478bd9Sstevel@tonic-gate fp_fksave(pfp); 277*7c478bd9Sstevel@tonic-gate else 278*7c478bd9Sstevel@tonic-gate fp_v8_fksave(pfp); 279*7c478bd9Sstevel@tonic-gate } 280*7c478bd9Sstevel@tonic-gate (void) kcopy(pfp, fp, sizeof (fp->fpu_fr)); 281*7c478bd9Sstevel@tonic-gate fp->fpu_q = pfp->fpu_q; 282*7c478bd9Sstevel@tonic-gate if (model == DATAMODEL_LP64) 283*7c478bd9Sstevel@tonic-gate fp->fpu_fsr = pfp->fpu_fsr; 284*7c478bd9Sstevel@tonic-gate else 285*7c478bd9Sstevel@tonic-gate fp->fpu_fsr = (uint32_t)pfp->fpu_fsr; 286*7c478bd9Sstevel@tonic-gate fp->fpu_qcnt = pfp->fpu_qcnt; 287*7c478bd9Sstevel@tonic-gate fp->fpu_q_entrysize = pfp->fpu_q_entrysize; 288*7c478bd9Sstevel@tonic-gate } else { 289*7c478bd9Sstevel@tonic-gate int i; 290*7c478bd9Sstevel@tonic-gate for (i = 0; i < 32; i++) /* NaN */ 291*7c478bd9Sstevel@tonic-gate ((uint32_t *)fp->fpu_fr.fpu_regs)[i] = (uint32_t)-1; 292*7c478bd9Sstevel@tonic-gate if (model == DATAMODEL_LP64) { 293*7c478bd9Sstevel@tonic-gate for (i = 16; i < 32; i++) /* NaN */ 294*7c478bd9Sstevel@tonic-gate ((uint64_t *)fp->fpu_fr.fpu_dregs)[i] = 295*7c478bd9Sstevel@tonic-gate (uint64_t)-1; 296*7c478bd9Sstevel@tonic-gate } 297*7c478bd9Sstevel@tonic-gate fp->fpu_fsr = 0; 298*7c478bd9Sstevel@tonic-gate fp->fpu_qcnt = 0; 299*7c478bd9Sstevel@tonic-gate } 300*7c478bd9Sstevel@tonic-gate kpreempt_enable(); 301*7c478bd9Sstevel@tonic-gate } 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 304*7c478bd9Sstevel@tonic-gate void 305*7c478bd9Sstevel@tonic-gate getfpregs32(klwp_t *lwp, fpregset32_t *fp) 306*7c478bd9Sstevel@tonic-gate { 307*7c478bd9Sstevel@tonic-gate fpregset_t fpregs; 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate getfpregs(lwp, &fpregs); 310*7c478bd9Sstevel@tonic-gate fpuregset_nto32(&fpregs, fp, NULL); 311*7c478bd9Sstevel@tonic-gate } 312*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 313*7c478bd9Sstevel@tonic-gate 314*7c478bd9Sstevel@tonic-gate /* 315*7c478bd9Sstevel@tonic-gate * Set general registers. 316*7c478bd9Sstevel@tonic-gate * NOTE: 'lwp' might not correspond to 'curthread' since this is 317*7c478bd9Sstevel@tonic-gate * called from code in /proc to set the registers of another lwp. 318*7c478bd9Sstevel@tonic-gate */ 319*7c478bd9Sstevel@tonic-gate 320*7c478bd9Sstevel@tonic-gate /* 64-bit gregset_t */ 321*7c478bd9Sstevel@tonic-gate void 322*7c478bd9Sstevel@tonic-gate setgregs(klwp_t *lwp, gregset_t grp) 323*7c478bd9Sstevel@tonic-gate { 324*7c478bd9Sstevel@tonic-gate struct regs *rp = lwptoregs(lwp); 325*7c478bd9Sstevel@tonic-gate kfpu_t *fp = lwptofpu(lwp); 326*7c478bd9Sstevel@tonic-gate uint64_t tbits; 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate int current = (lwp == curthread->t_lwp); 329*7c478bd9Sstevel@tonic-gate 330*7c478bd9Sstevel@tonic-gate if (current) 331*7c478bd9Sstevel@tonic-gate (void) save_syscall_args(); /* copy the args first */ 332*7c478bd9Sstevel@tonic-gate 333*7c478bd9Sstevel@tonic-gate tbits = (((grp[REG_CCR] & TSTATE_CCR_MASK) << TSTATE_CCR_SHIFT) | 334*7c478bd9Sstevel@tonic-gate ((grp[REG_ASI] & TSTATE_ASI_MASK) << TSTATE_ASI_SHIFT)); 335*7c478bd9Sstevel@tonic-gate rp->r_tstate &= ~(((uint64_t)TSTATE_CCR_MASK << TSTATE_CCR_SHIFT) | 336*7c478bd9Sstevel@tonic-gate ((uint64_t)TSTATE_ASI_MASK << TSTATE_ASI_SHIFT)); 337*7c478bd9Sstevel@tonic-gate rp->r_tstate |= tbits; 338*7c478bd9Sstevel@tonic-gate kpreempt_disable(); 339*7c478bd9Sstevel@tonic-gate fp->fpu_fprs = (uint32_t)grp[REG_FPRS]; 340*7c478bd9Sstevel@tonic-gate if (fpu_exists && (current) && (fp->fpu_fprs & FPRS_FEF)) 341*7c478bd9Sstevel@tonic-gate _fp_write_fprs(fp->fpu_fprs); 342*7c478bd9Sstevel@tonic-gate kpreempt_enable(); 343*7c478bd9Sstevel@tonic-gate 344*7c478bd9Sstevel@tonic-gate /* 345*7c478bd9Sstevel@tonic-gate * pc and npc must be 4-byte aligned on sparc. 346*7c478bd9Sstevel@tonic-gate * We silently make it so to avoid a watchdog reset. 347*7c478bd9Sstevel@tonic-gate */ 348*7c478bd9Sstevel@tonic-gate rp->r_pc = grp[REG_PC] & ~03L; 349*7c478bd9Sstevel@tonic-gate rp->r_npc = grp[REG_nPC] & ~03L; 350*7c478bd9Sstevel@tonic-gate rp->r_y = grp[REG_Y]; 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate rp->r_g1 = grp[REG_G1]; 353*7c478bd9Sstevel@tonic-gate rp->r_g2 = grp[REG_G2]; 354*7c478bd9Sstevel@tonic-gate rp->r_g3 = grp[REG_G3]; 355*7c478bd9Sstevel@tonic-gate rp->r_g4 = grp[REG_G4]; 356*7c478bd9Sstevel@tonic-gate rp->r_g5 = grp[REG_G5]; 357*7c478bd9Sstevel@tonic-gate rp->r_g6 = grp[REG_G6]; 358*7c478bd9Sstevel@tonic-gate rp->r_g7 = grp[REG_G7]; 359*7c478bd9Sstevel@tonic-gate 360*7c478bd9Sstevel@tonic-gate rp->r_o0 = grp[REG_O0]; 361*7c478bd9Sstevel@tonic-gate rp->r_o1 = grp[REG_O1]; 362*7c478bd9Sstevel@tonic-gate rp->r_o2 = grp[REG_O2]; 363*7c478bd9Sstevel@tonic-gate rp->r_o3 = grp[REG_O3]; 364*7c478bd9Sstevel@tonic-gate rp->r_o4 = grp[REG_O4]; 365*7c478bd9Sstevel@tonic-gate rp->r_o5 = grp[REG_O5]; 366*7c478bd9Sstevel@tonic-gate rp->r_o6 = grp[REG_O6]; 367*7c478bd9Sstevel@tonic-gate rp->r_o7 = grp[REG_O7]; 368*7c478bd9Sstevel@tonic-gate 369*7c478bd9Sstevel@tonic-gate if (current) { 370*7c478bd9Sstevel@tonic-gate /* 371*7c478bd9Sstevel@tonic-gate * This was called from a system call, but we 372*7c478bd9Sstevel@tonic-gate * do not want to return via the shared window; 373*7c478bd9Sstevel@tonic-gate * restoring the CPU context changes everything. 374*7c478bd9Sstevel@tonic-gate */ 375*7c478bd9Sstevel@tonic-gate lwp->lwp_eosys = JUSTRETURN; 376*7c478bd9Sstevel@tonic-gate curthread->t_post_sys = 1; 377*7c478bd9Sstevel@tonic-gate } 378*7c478bd9Sstevel@tonic-gate } 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate /* 381*7c478bd9Sstevel@tonic-gate * Return the general registers. 382*7c478bd9Sstevel@tonic-gate * NOTE: 'lwp' might not correspond to 'curthread' since this is 383*7c478bd9Sstevel@tonic-gate * called from code in /proc to get the registers of another lwp. 384*7c478bd9Sstevel@tonic-gate */ 385*7c478bd9Sstevel@tonic-gate void 386*7c478bd9Sstevel@tonic-gate getgregs(klwp_t *lwp, gregset_t grp) 387*7c478bd9Sstevel@tonic-gate { 388*7c478bd9Sstevel@tonic-gate struct regs *rp = lwptoregs(lwp); 389*7c478bd9Sstevel@tonic-gate uint32_t fprs; 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate kpreempt_disable(); 392*7c478bd9Sstevel@tonic-gate if (fpu_exists && ttolwp(curthread) == lwp) { 393*7c478bd9Sstevel@tonic-gate fprs = _fp_read_fprs(); 394*7c478bd9Sstevel@tonic-gate } else { 395*7c478bd9Sstevel@tonic-gate kfpu_t *fp = lwptofpu(lwp); 396*7c478bd9Sstevel@tonic-gate fprs = fp->fpu_fprs; 397*7c478bd9Sstevel@tonic-gate } 398*7c478bd9Sstevel@tonic-gate kpreempt_enable(); 399*7c478bd9Sstevel@tonic-gate grp[REG_CCR] = (rp->r_tstate >> TSTATE_CCR_SHIFT) & TSTATE_CCR_MASK; 400*7c478bd9Sstevel@tonic-gate grp[REG_PC] = rp->r_pc; 401*7c478bd9Sstevel@tonic-gate grp[REG_nPC] = rp->r_npc; 402*7c478bd9Sstevel@tonic-gate grp[REG_Y] = (uint32_t)rp->r_y; 403*7c478bd9Sstevel@tonic-gate grp[REG_G1] = rp->r_g1; 404*7c478bd9Sstevel@tonic-gate grp[REG_G2] = rp->r_g2; 405*7c478bd9Sstevel@tonic-gate grp[REG_G3] = rp->r_g3; 406*7c478bd9Sstevel@tonic-gate grp[REG_G4] = rp->r_g4; 407*7c478bd9Sstevel@tonic-gate grp[REG_G5] = rp->r_g5; 408*7c478bd9Sstevel@tonic-gate grp[REG_G6] = rp->r_g6; 409*7c478bd9Sstevel@tonic-gate grp[REG_G7] = rp->r_g7; 410*7c478bd9Sstevel@tonic-gate grp[REG_O0] = rp->r_o0; 411*7c478bd9Sstevel@tonic-gate grp[REG_O1] = rp->r_o1; 412*7c478bd9Sstevel@tonic-gate grp[REG_O2] = rp->r_o2; 413*7c478bd9Sstevel@tonic-gate grp[REG_O3] = rp->r_o3; 414*7c478bd9Sstevel@tonic-gate grp[REG_O4] = rp->r_o4; 415*7c478bd9Sstevel@tonic-gate grp[REG_O5] = rp->r_o5; 416*7c478bd9Sstevel@tonic-gate grp[REG_O6] = rp->r_o6; 417*7c478bd9Sstevel@tonic-gate grp[REG_O7] = rp->r_o7; 418*7c478bd9Sstevel@tonic-gate grp[REG_ASI] = (rp->r_tstate >> TSTATE_ASI_SHIFT) & TSTATE_ASI_MASK; 419*7c478bd9Sstevel@tonic-gate grp[REG_FPRS] = fprs; 420*7c478bd9Sstevel@tonic-gate } 421*7c478bd9Sstevel@tonic-gate 422*7c478bd9Sstevel@tonic-gate void 423*7c478bd9Sstevel@tonic-gate getgregs32(klwp_t *lwp, gregset32_t grp) 424*7c478bd9Sstevel@tonic-gate { 425*7c478bd9Sstevel@tonic-gate struct regs *rp = lwptoregs(lwp); 426*7c478bd9Sstevel@tonic-gate uint32_t fprs; 427*7c478bd9Sstevel@tonic-gate 428*7c478bd9Sstevel@tonic-gate kpreempt_disable(); 429*7c478bd9Sstevel@tonic-gate if (fpu_exists && ttolwp(curthread) == lwp) { 430*7c478bd9Sstevel@tonic-gate fprs = _fp_read_fprs(); 431*7c478bd9Sstevel@tonic-gate } else { 432*7c478bd9Sstevel@tonic-gate kfpu_t *fp = lwptofpu(lwp); 433*7c478bd9Sstevel@tonic-gate fprs = fp->fpu_fprs; 434*7c478bd9Sstevel@tonic-gate } 435*7c478bd9Sstevel@tonic-gate kpreempt_enable(); 436*7c478bd9Sstevel@tonic-gate grp[REG_PSR] = mkpsr(rp->r_tstate, fprs); 437*7c478bd9Sstevel@tonic-gate grp[REG_PC] = rp->r_pc; 438*7c478bd9Sstevel@tonic-gate grp[REG_nPC] = rp->r_npc; 439*7c478bd9Sstevel@tonic-gate grp[REG_Y] = rp->r_y; 440*7c478bd9Sstevel@tonic-gate grp[REG_G1] = rp->r_g1; 441*7c478bd9Sstevel@tonic-gate grp[REG_G2] = rp->r_g2; 442*7c478bd9Sstevel@tonic-gate grp[REG_G3] = rp->r_g3; 443*7c478bd9Sstevel@tonic-gate grp[REG_G4] = rp->r_g4; 444*7c478bd9Sstevel@tonic-gate grp[REG_G5] = rp->r_g5; 445*7c478bd9Sstevel@tonic-gate grp[REG_G6] = rp->r_g6; 446*7c478bd9Sstevel@tonic-gate grp[REG_G7] = rp->r_g7; 447*7c478bd9Sstevel@tonic-gate grp[REG_O0] = rp->r_o0; 448*7c478bd9Sstevel@tonic-gate grp[REG_O1] = rp->r_o1; 449*7c478bd9Sstevel@tonic-gate grp[REG_O2] = rp->r_o2; 450*7c478bd9Sstevel@tonic-gate grp[REG_O3] = rp->r_o3; 451*7c478bd9Sstevel@tonic-gate grp[REG_O4] = rp->r_o4; 452*7c478bd9Sstevel@tonic-gate grp[REG_O5] = rp->r_o5; 453*7c478bd9Sstevel@tonic-gate grp[REG_O6] = rp->r_o6; 454*7c478bd9Sstevel@tonic-gate grp[REG_O7] = rp->r_o7; 455*7c478bd9Sstevel@tonic-gate } 456*7c478bd9Sstevel@tonic-gate 457*7c478bd9Sstevel@tonic-gate /* 458*7c478bd9Sstevel@tonic-gate * Return the user-level PC. 459*7c478bd9Sstevel@tonic-gate * If in a system call, return the address of the syscall trap. 460*7c478bd9Sstevel@tonic-gate */ 461*7c478bd9Sstevel@tonic-gate greg_t 462*7c478bd9Sstevel@tonic-gate getuserpc() 463*7c478bd9Sstevel@tonic-gate { 464*7c478bd9Sstevel@tonic-gate return (lwptoregs(ttolwp(curthread))->r_pc); 465*7c478bd9Sstevel@tonic-gate } 466*7c478bd9Sstevel@tonic-gate 467*7c478bd9Sstevel@tonic-gate /* 468*7c478bd9Sstevel@tonic-gate * Set register windows. 469*7c478bd9Sstevel@tonic-gate */ 470*7c478bd9Sstevel@tonic-gate void 471*7c478bd9Sstevel@tonic-gate setgwins(klwp_t *lwp, gwindows_t *gwins) 472*7c478bd9Sstevel@tonic-gate { 473*7c478bd9Sstevel@tonic-gate struct machpcb *mpcb = lwptompcb(lwp); 474*7c478bd9Sstevel@tonic-gate int wbcnt = gwins->wbcnt; 475*7c478bd9Sstevel@tonic-gate caddr_t sp; 476*7c478bd9Sstevel@tonic-gate int i; 477*7c478bd9Sstevel@tonic-gate struct rwindow32 *rwp; 478*7c478bd9Sstevel@tonic-gate int wbuf_rwindow_size; 479*7c478bd9Sstevel@tonic-gate int is64; 480*7c478bd9Sstevel@tonic-gate 481*7c478bd9Sstevel@tonic-gate if (mpcb->mpcb_wstate == WSTATE_USER32) { 482*7c478bd9Sstevel@tonic-gate wbuf_rwindow_size = WINDOWSIZE32; 483*7c478bd9Sstevel@tonic-gate is64 = 0; 484*7c478bd9Sstevel@tonic-gate } else { 485*7c478bd9Sstevel@tonic-gate wbuf_rwindow_size = WINDOWSIZE64; 486*7c478bd9Sstevel@tonic-gate is64 = 1; 487*7c478bd9Sstevel@tonic-gate } 488*7c478bd9Sstevel@tonic-gate ASSERT(wbcnt >= 0 && wbcnt <= SPARC_MAXREGWINDOW); 489*7c478bd9Sstevel@tonic-gate mpcb->mpcb_wbcnt = 0; 490*7c478bd9Sstevel@tonic-gate for (i = 0; i < wbcnt; i++) { 491*7c478bd9Sstevel@tonic-gate sp = (caddr_t)gwins->spbuf[i]; 492*7c478bd9Sstevel@tonic-gate mpcb->mpcb_spbuf[i] = sp; 493*7c478bd9Sstevel@tonic-gate rwp = (struct rwindow32 *) 494*7c478bd9Sstevel@tonic-gate (mpcb->mpcb_wbuf + (i * wbuf_rwindow_size)); 495*7c478bd9Sstevel@tonic-gate if (is64 && IS_V9STACK(sp)) 496*7c478bd9Sstevel@tonic-gate bcopy(&gwins->wbuf[i], rwp, sizeof (struct rwindow)); 497*7c478bd9Sstevel@tonic-gate else 498*7c478bd9Sstevel@tonic-gate rwindow_nto32(&gwins->wbuf[i], rwp); 499*7c478bd9Sstevel@tonic-gate mpcb->mpcb_wbcnt++; 500*7c478bd9Sstevel@tonic-gate } 501*7c478bd9Sstevel@tonic-gate } 502*7c478bd9Sstevel@tonic-gate 503*7c478bd9Sstevel@tonic-gate void 504*7c478bd9Sstevel@tonic-gate setgwins32(klwp_t *lwp, gwindows32_t *gwins) 505*7c478bd9Sstevel@tonic-gate { 506*7c478bd9Sstevel@tonic-gate struct machpcb *mpcb = lwptompcb(lwp); 507*7c478bd9Sstevel@tonic-gate int wbcnt = gwins->wbcnt; 508*7c478bd9Sstevel@tonic-gate caddr_t sp; 509*7c478bd9Sstevel@tonic-gate int i; 510*7c478bd9Sstevel@tonic-gate 511*7c478bd9Sstevel@tonic-gate struct rwindow *rwp; 512*7c478bd9Sstevel@tonic-gate int wbuf_rwindow_size; 513*7c478bd9Sstevel@tonic-gate int is64; 514*7c478bd9Sstevel@tonic-gate 515*7c478bd9Sstevel@tonic-gate if (mpcb->mpcb_wstate == WSTATE_USER32) { 516*7c478bd9Sstevel@tonic-gate wbuf_rwindow_size = WINDOWSIZE32; 517*7c478bd9Sstevel@tonic-gate is64 = 0; 518*7c478bd9Sstevel@tonic-gate } else { 519*7c478bd9Sstevel@tonic-gate wbuf_rwindow_size = WINDOWSIZE64; 520*7c478bd9Sstevel@tonic-gate is64 = 1; 521*7c478bd9Sstevel@tonic-gate } 522*7c478bd9Sstevel@tonic-gate 523*7c478bd9Sstevel@tonic-gate ASSERT(wbcnt >= 0 && wbcnt <= SPARC_MAXREGWINDOW); 524*7c478bd9Sstevel@tonic-gate mpcb->mpcb_wbcnt = 0; 525*7c478bd9Sstevel@tonic-gate for (i = 0; i < wbcnt; i++) { 526*7c478bd9Sstevel@tonic-gate sp = (caddr_t)gwins->spbuf[i]; 527*7c478bd9Sstevel@tonic-gate mpcb->mpcb_spbuf[i] = sp; 528*7c478bd9Sstevel@tonic-gate rwp = (struct rwindow *) 529*7c478bd9Sstevel@tonic-gate (mpcb->mpcb_wbuf + (i * wbuf_rwindow_size)); 530*7c478bd9Sstevel@tonic-gate if (is64 && IS_V9STACK(sp)) 531*7c478bd9Sstevel@tonic-gate rwindow_32ton(&gwins->wbuf[i], rwp); 532*7c478bd9Sstevel@tonic-gate else 533*7c478bd9Sstevel@tonic-gate bcopy(&gwins->wbuf[i], rwp, sizeof (struct rwindow32)); 534*7c478bd9Sstevel@tonic-gate mpcb->mpcb_wbcnt++; 535*7c478bd9Sstevel@tonic-gate } 536*7c478bd9Sstevel@tonic-gate } 537*7c478bd9Sstevel@tonic-gate 538*7c478bd9Sstevel@tonic-gate /* 539*7c478bd9Sstevel@tonic-gate * Get register windows. 540*7c478bd9Sstevel@tonic-gate * NOTE: 'lwp' might not correspond to 'curthread' since this is 541*7c478bd9Sstevel@tonic-gate * called from code in /proc to set the registers of another lwp. 542*7c478bd9Sstevel@tonic-gate */ 543*7c478bd9Sstevel@tonic-gate void 544*7c478bd9Sstevel@tonic-gate getgwins(klwp_t *lwp, gwindows_t *gwp) 545*7c478bd9Sstevel@tonic-gate { 546*7c478bd9Sstevel@tonic-gate struct machpcb *mpcb = lwptompcb(lwp); 547*7c478bd9Sstevel@tonic-gate int wbcnt = mpcb->mpcb_wbcnt; 548*7c478bd9Sstevel@tonic-gate caddr_t sp; 549*7c478bd9Sstevel@tonic-gate int i; 550*7c478bd9Sstevel@tonic-gate struct rwindow32 *rwp; 551*7c478bd9Sstevel@tonic-gate int wbuf_rwindow_size; 552*7c478bd9Sstevel@tonic-gate int is64; 553*7c478bd9Sstevel@tonic-gate 554*7c478bd9Sstevel@tonic-gate if (mpcb->mpcb_wstate == WSTATE_USER32) { 555*7c478bd9Sstevel@tonic-gate wbuf_rwindow_size = WINDOWSIZE32; 556*7c478bd9Sstevel@tonic-gate is64 = 0; 557*7c478bd9Sstevel@tonic-gate } else { 558*7c478bd9Sstevel@tonic-gate wbuf_rwindow_size = WINDOWSIZE64; 559*7c478bd9Sstevel@tonic-gate is64 = 1; 560*7c478bd9Sstevel@tonic-gate } 561*7c478bd9Sstevel@tonic-gate ASSERT(wbcnt >= 0 && wbcnt <= SPARC_MAXREGWINDOW); 562*7c478bd9Sstevel@tonic-gate gwp->wbcnt = wbcnt; 563*7c478bd9Sstevel@tonic-gate for (i = 0; i < wbcnt; i++) { 564*7c478bd9Sstevel@tonic-gate sp = mpcb->mpcb_spbuf[i]; 565*7c478bd9Sstevel@tonic-gate gwp->spbuf[i] = (greg_t *)sp; 566*7c478bd9Sstevel@tonic-gate rwp = (struct rwindow32 *) 567*7c478bd9Sstevel@tonic-gate (mpcb->mpcb_wbuf + (i * wbuf_rwindow_size)); 568*7c478bd9Sstevel@tonic-gate if (is64 && IS_V9STACK(sp)) 569*7c478bd9Sstevel@tonic-gate bcopy(rwp, &gwp->wbuf[i], sizeof (struct rwindow)); 570*7c478bd9Sstevel@tonic-gate else 571*7c478bd9Sstevel@tonic-gate rwindow_32ton(rwp, &gwp->wbuf[i]); 572*7c478bd9Sstevel@tonic-gate } 573*7c478bd9Sstevel@tonic-gate } 574*7c478bd9Sstevel@tonic-gate 575*7c478bd9Sstevel@tonic-gate void 576*7c478bd9Sstevel@tonic-gate getgwins32(klwp_t *lwp, gwindows32_t *gwp) 577*7c478bd9Sstevel@tonic-gate { 578*7c478bd9Sstevel@tonic-gate struct machpcb *mpcb = lwptompcb(lwp); 579*7c478bd9Sstevel@tonic-gate int wbcnt = mpcb->mpcb_wbcnt; 580*7c478bd9Sstevel@tonic-gate int i; 581*7c478bd9Sstevel@tonic-gate struct rwindow *rwp; 582*7c478bd9Sstevel@tonic-gate int wbuf_rwindow_size; 583*7c478bd9Sstevel@tonic-gate caddr_t sp; 584*7c478bd9Sstevel@tonic-gate int is64; 585*7c478bd9Sstevel@tonic-gate 586*7c478bd9Sstevel@tonic-gate if (mpcb->mpcb_wstate == WSTATE_USER32) { 587*7c478bd9Sstevel@tonic-gate wbuf_rwindow_size = WINDOWSIZE32; 588*7c478bd9Sstevel@tonic-gate is64 = 0; 589*7c478bd9Sstevel@tonic-gate } else { 590*7c478bd9Sstevel@tonic-gate wbuf_rwindow_size = WINDOWSIZE64; 591*7c478bd9Sstevel@tonic-gate is64 = 1; 592*7c478bd9Sstevel@tonic-gate } 593*7c478bd9Sstevel@tonic-gate 594*7c478bd9Sstevel@tonic-gate ASSERT(wbcnt >= 0 && wbcnt <= SPARC_MAXREGWINDOW); 595*7c478bd9Sstevel@tonic-gate gwp->wbcnt = wbcnt; 596*7c478bd9Sstevel@tonic-gate for (i = 0; i < wbcnt; i++) { 597*7c478bd9Sstevel@tonic-gate sp = mpcb->mpcb_spbuf[i]; 598*7c478bd9Sstevel@tonic-gate rwp = (struct rwindow *) 599*7c478bd9Sstevel@tonic-gate (mpcb->mpcb_wbuf + (i * wbuf_rwindow_size)); 600*7c478bd9Sstevel@tonic-gate gwp->spbuf[i] = (caddr32_t)sp; 601*7c478bd9Sstevel@tonic-gate if (is64 && IS_V9STACK(sp)) 602*7c478bd9Sstevel@tonic-gate rwindow_nto32(rwp, &gwp->wbuf[i]); 603*7c478bd9Sstevel@tonic-gate else 604*7c478bd9Sstevel@tonic-gate bcopy(rwp, &gwp->wbuf[i], sizeof (struct rwindow32)); 605*7c478bd9Sstevel@tonic-gate } 606*7c478bd9Sstevel@tonic-gate } 607*7c478bd9Sstevel@tonic-gate 608*7c478bd9Sstevel@tonic-gate /* 609*7c478bd9Sstevel@tonic-gate * For things that depend on register state being on the stack, 610*7c478bd9Sstevel@tonic-gate * copy any register windows that get saved into the window buffer 611*7c478bd9Sstevel@tonic-gate * (in the pcb) onto the stack. This normally gets fixed up 612*7c478bd9Sstevel@tonic-gate * before returning to a user program. Callers of this routine 613*7c478bd9Sstevel@tonic-gate * require this to happen immediately because a later kernel 614*7c478bd9Sstevel@tonic-gate * operation depends on window state (like instruction simulation). 615*7c478bd9Sstevel@tonic-gate */ 616*7c478bd9Sstevel@tonic-gate int 617*7c478bd9Sstevel@tonic-gate flush_user_windows_to_stack(caddr_t *psp) 618*7c478bd9Sstevel@tonic-gate { 619*7c478bd9Sstevel@tonic-gate int j, k; 620*7c478bd9Sstevel@tonic-gate caddr_t sp; 621*7c478bd9Sstevel@tonic-gate struct machpcb *mpcb = lwptompcb(ttolwp(curthread)); 622*7c478bd9Sstevel@tonic-gate int err; 623*7c478bd9Sstevel@tonic-gate int error = 0; 624*7c478bd9Sstevel@tonic-gate int wbuf_rwindow_size; 625*7c478bd9Sstevel@tonic-gate int rwindow_size; 626*7c478bd9Sstevel@tonic-gate int stack_align; 627*7c478bd9Sstevel@tonic-gate int watched; 628*7c478bd9Sstevel@tonic-gate 629*7c478bd9Sstevel@tonic-gate flush_user_windows(); 630*7c478bd9Sstevel@tonic-gate 631*7c478bd9Sstevel@tonic-gate if (mpcb->mpcb_wstate != WSTATE_USER32) 632*7c478bd9Sstevel@tonic-gate wbuf_rwindow_size = WINDOWSIZE64; 633*7c478bd9Sstevel@tonic-gate else 634*7c478bd9Sstevel@tonic-gate wbuf_rwindow_size = WINDOWSIZE32; 635*7c478bd9Sstevel@tonic-gate 636*7c478bd9Sstevel@tonic-gate j = mpcb->mpcb_wbcnt; 637*7c478bd9Sstevel@tonic-gate while (j > 0) { 638*7c478bd9Sstevel@tonic-gate sp = mpcb->mpcb_spbuf[--j]; 639*7c478bd9Sstevel@tonic-gate 640*7c478bd9Sstevel@tonic-gate if ((mpcb->mpcb_wstate != WSTATE_USER32) && 641*7c478bd9Sstevel@tonic-gate IS_V9STACK(sp)) { 642*7c478bd9Sstevel@tonic-gate sp += V9BIAS64; 643*7c478bd9Sstevel@tonic-gate stack_align = STACK_ALIGN64; 644*7c478bd9Sstevel@tonic-gate rwindow_size = WINDOWSIZE64; 645*7c478bd9Sstevel@tonic-gate } else { 646*7c478bd9Sstevel@tonic-gate sp = (caddr_t)(uint32_t)sp; 647*7c478bd9Sstevel@tonic-gate stack_align = STACK_ALIGN32; 648*7c478bd9Sstevel@tonic-gate rwindow_size = WINDOWSIZE32; 649*7c478bd9Sstevel@tonic-gate } 650*7c478bd9Sstevel@tonic-gate if (((uintptr_t)sp & (stack_align - 1)) != 0) 651*7c478bd9Sstevel@tonic-gate continue; 652*7c478bd9Sstevel@tonic-gate 653*7c478bd9Sstevel@tonic-gate watched = watch_disable_addr(sp, rwindow_size, S_WRITE); 654*7c478bd9Sstevel@tonic-gate err = xcopyout(mpcb->mpcb_wbuf + 655*7c478bd9Sstevel@tonic-gate (j * wbuf_rwindow_size), sp, rwindow_size); 656*7c478bd9Sstevel@tonic-gate if (err != 0) { 657*7c478bd9Sstevel@tonic-gate if (psp != NULL) { 658*7c478bd9Sstevel@tonic-gate /* 659*7c478bd9Sstevel@tonic-gate * Determine the offending address. 660*7c478bd9Sstevel@tonic-gate * It may not be the stack pointer itself. 661*7c478bd9Sstevel@tonic-gate */ 662*7c478bd9Sstevel@tonic-gate uint_t *kaddr = (uint_t *)(mpcb->mpcb_wbuf + 663*7c478bd9Sstevel@tonic-gate (j * wbuf_rwindow_size)); 664*7c478bd9Sstevel@tonic-gate uint_t *uaddr = (uint_t *)sp; 665*7c478bd9Sstevel@tonic-gate 666*7c478bd9Sstevel@tonic-gate for (k = 0; 667*7c478bd9Sstevel@tonic-gate k < rwindow_size / sizeof (int); 668*7c478bd9Sstevel@tonic-gate k++, kaddr++, uaddr++) { 669*7c478bd9Sstevel@tonic-gate if (suword32(uaddr, *kaddr)) 670*7c478bd9Sstevel@tonic-gate break; 671*7c478bd9Sstevel@tonic-gate } 672*7c478bd9Sstevel@tonic-gate 673*7c478bd9Sstevel@tonic-gate /* can't happen? */ 674*7c478bd9Sstevel@tonic-gate if (k == rwindow_size / sizeof (int)) 675*7c478bd9Sstevel@tonic-gate uaddr = (uint_t *)sp; 676*7c478bd9Sstevel@tonic-gate 677*7c478bd9Sstevel@tonic-gate *psp = (caddr_t)uaddr; 678*7c478bd9Sstevel@tonic-gate } 679*7c478bd9Sstevel@tonic-gate error = err; 680*7c478bd9Sstevel@tonic-gate } else { 681*7c478bd9Sstevel@tonic-gate /* 682*7c478bd9Sstevel@tonic-gate * stack was aligned and copyout succeeded; 683*7c478bd9Sstevel@tonic-gate * move other windows down. 684*7c478bd9Sstevel@tonic-gate */ 685*7c478bd9Sstevel@tonic-gate mpcb->mpcb_wbcnt--; 686*7c478bd9Sstevel@tonic-gate for (k = j; k < mpcb->mpcb_wbcnt; k++) { 687*7c478bd9Sstevel@tonic-gate mpcb->mpcb_spbuf[k] = mpcb->mpcb_spbuf[k+1]; 688*7c478bd9Sstevel@tonic-gate bcopy( 689*7c478bd9Sstevel@tonic-gate mpcb->mpcb_wbuf + 690*7c478bd9Sstevel@tonic-gate ((k+1) * wbuf_rwindow_size), 691*7c478bd9Sstevel@tonic-gate mpcb->mpcb_wbuf + 692*7c478bd9Sstevel@tonic-gate (k * wbuf_rwindow_size), 693*7c478bd9Sstevel@tonic-gate wbuf_rwindow_size); 694*7c478bd9Sstevel@tonic-gate } 695*7c478bd9Sstevel@tonic-gate } 696*7c478bd9Sstevel@tonic-gate if (watched) 697*7c478bd9Sstevel@tonic-gate watch_enable_addr(sp, rwindow_size, S_WRITE); 698*7c478bd9Sstevel@tonic-gate } /* while there are windows in the wbuf */ 699*7c478bd9Sstevel@tonic-gate return (error); 700*7c478bd9Sstevel@tonic-gate } 701*7c478bd9Sstevel@tonic-gate 702*7c478bd9Sstevel@tonic-gate static int 703*7c478bd9Sstevel@tonic-gate copy_return_window32(int dotwo) 704*7c478bd9Sstevel@tonic-gate { 705*7c478bd9Sstevel@tonic-gate klwp_t *lwp = ttolwp(curthread); 706*7c478bd9Sstevel@tonic-gate struct machpcb *mpcb = lwptompcb(lwp); 707*7c478bd9Sstevel@tonic-gate struct rwindow32 rwindow32; 708*7c478bd9Sstevel@tonic-gate caddr_t sp1; 709*7c478bd9Sstevel@tonic-gate caddr_t sp2; 710*7c478bd9Sstevel@tonic-gate 711*7c478bd9Sstevel@tonic-gate (void) flush_user_windows_to_stack(NULL); 712*7c478bd9Sstevel@tonic-gate if (mpcb->mpcb_rsp[0] == NULL) { 713*7c478bd9Sstevel@tonic-gate sp1 = (caddr_t)(uint32_t)lwptoregs(lwp)->r_sp; 714*7c478bd9Sstevel@tonic-gate if ((copyin_nowatch(sp1, &rwindow32, 715*7c478bd9Sstevel@tonic-gate sizeof (struct rwindow32))) == 0) 716*7c478bd9Sstevel@tonic-gate mpcb->mpcb_rsp[0] = sp1; 717*7c478bd9Sstevel@tonic-gate rwindow_32ton(&rwindow32, &mpcb->mpcb_rwin[0]); 718*7c478bd9Sstevel@tonic-gate } 719*7c478bd9Sstevel@tonic-gate mpcb->mpcb_rsp[1] = NULL; 720*7c478bd9Sstevel@tonic-gate if (dotwo && mpcb->mpcb_rsp[0] != NULL && 721*7c478bd9Sstevel@tonic-gate (sp2 = (caddr_t)mpcb->mpcb_rwin[0].rw_fp) != NULL) { 722*7c478bd9Sstevel@tonic-gate if ((copyin_nowatch(sp2, &rwindow32, 723*7c478bd9Sstevel@tonic-gate sizeof (struct rwindow32)) == 0)) 724*7c478bd9Sstevel@tonic-gate mpcb->mpcb_rsp[1] = sp2; 725*7c478bd9Sstevel@tonic-gate rwindow_32ton(&rwindow32, &mpcb->mpcb_rwin[1]); 726*7c478bd9Sstevel@tonic-gate } 727*7c478bd9Sstevel@tonic-gate return (mpcb->mpcb_rsp[0] != NULL); 728*7c478bd9Sstevel@tonic-gate } 729*7c478bd9Sstevel@tonic-gate 730*7c478bd9Sstevel@tonic-gate int 731*7c478bd9Sstevel@tonic-gate copy_return_window(int dotwo) 732*7c478bd9Sstevel@tonic-gate { 733*7c478bd9Sstevel@tonic-gate proc_t *p = ttoproc(curthread); 734*7c478bd9Sstevel@tonic-gate klwp_t *lwp; 735*7c478bd9Sstevel@tonic-gate struct machpcb *mpcb; 736*7c478bd9Sstevel@tonic-gate caddr_t sp1; 737*7c478bd9Sstevel@tonic-gate caddr_t sp2; 738*7c478bd9Sstevel@tonic-gate 739*7c478bd9Sstevel@tonic-gate if (p->p_model == DATAMODEL_ILP32) 740*7c478bd9Sstevel@tonic-gate return (copy_return_window32(dotwo)); 741*7c478bd9Sstevel@tonic-gate 742*7c478bd9Sstevel@tonic-gate lwp = ttolwp(curthread); 743*7c478bd9Sstevel@tonic-gate mpcb = lwptompcb(lwp); 744*7c478bd9Sstevel@tonic-gate (void) flush_user_windows_to_stack(NULL); 745*7c478bd9Sstevel@tonic-gate if (mpcb->mpcb_rsp[0] == NULL) { 746*7c478bd9Sstevel@tonic-gate sp1 = (caddr_t)lwptoregs(lwp)->r_sp + STACK_BIAS; 747*7c478bd9Sstevel@tonic-gate if ((copyin_nowatch(sp1, &mpcb->mpcb_rwin[0], 748*7c478bd9Sstevel@tonic-gate sizeof (struct rwindow)) == 0)) 749*7c478bd9Sstevel@tonic-gate mpcb->mpcb_rsp[0] = sp1 - STACK_BIAS; 750*7c478bd9Sstevel@tonic-gate } 751*7c478bd9Sstevel@tonic-gate mpcb->mpcb_rsp[1] = NULL; 752*7c478bd9Sstevel@tonic-gate if (dotwo && mpcb->mpcb_rsp[0] != NULL && 753*7c478bd9Sstevel@tonic-gate (sp2 = (caddr_t)mpcb->mpcb_rwin[0].rw_fp) != NULL) { 754*7c478bd9Sstevel@tonic-gate sp2 += STACK_BIAS; 755*7c478bd9Sstevel@tonic-gate if ((copyin_nowatch(sp2, &mpcb->mpcb_rwin[1], 756*7c478bd9Sstevel@tonic-gate sizeof (struct rwindow)) == 0)) 757*7c478bd9Sstevel@tonic-gate mpcb->mpcb_rsp[1] = sp2 - STACK_BIAS; 758*7c478bd9Sstevel@tonic-gate } 759*7c478bd9Sstevel@tonic-gate return (mpcb->mpcb_rsp[0] != NULL); 760*7c478bd9Sstevel@tonic-gate } 761*7c478bd9Sstevel@tonic-gate 762*7c478bd9Sstevel@tonic-gate /* 763*7c478bd9Sstevel@tonic-gate * Clear registers on exec(2). 764*7c478bd9Sstevel@tonic-gate */ 765*7c478bd9Sstevel@tonic-gate void 766*7c478bd9Sstevel@tonic-gate setregs(uarg_t *args) 767*7c478bd9Sstevel@tonic-gate { 768*7c478bd9Sstevel@tonic-gate struct regs *rp; 769*7c478bd9Sstevel@tonic-gate klwp_t *lwp = ttolwp(curthread); 770*7c478bd9Sstevel@tonic-gate kfpu_t *fpp = lwptofpu(lwp); 771*7c478bd9Sstevel@tonic-gate struct machpcb *mpcb = lwptompcb(lwp); 772*7c478bd9Sstevel@tonic-gate proc_t *p = ttoproc(curthread); 773*7c478bd9Sstevel@tonic-gate 774*7c478bd9Sstevel@tonic-gate /* 775*7c478bd9Sstevel@tonic-gate * Initialize user registers. 776*7c478bd9Sstevel@tonic-gate */ 777*7c478bd9Sstevel@tonic-gate (void) save_syscall_args(); /* copy args from registers first */ 778*7c478bd9Sstevel@tonic-gate rp = lwptoregs(lwp); 779*7c478bd9Sstevel@tonic-gate rp->r_g1 = rp->r_g2 = rp->r_g3 = rp->r_g4 = rp->r_g5 = 780*7c478bd9Sstevel@tonic-gate rp->r_g6 = rp->r_o0 = rp->r_o1 = rp->r_o2 = 781*7c478bd9Sstevel@tonic-gate rp->r_o3 = rp->r_o4 = rp->r_o5 = rp->r_o7 = 0; 782*7c478bd9Sstevel@tonic-gate if (p->p_model == DATAMODEL_ILP32) 783*7c478bd9Sstevel@tonic-gate rp->r_tstate = TSTATE_USER32; 784*7c478bd9Sstevel@tonic-gate else 785*7c478bd9Sstevel@tonic-gate rp->r_tstate = TSTATE_USER64; 786*7c478bd9Sstevel@tonic-gate if (!fpu_exists) 787*7c478bd9Sstevel@tonic-gate rp->r_tstate &= ~TSTATE_PEF; 788*7c478bd9Sstevel@tonic-gate rp->r_g7 = args->thrptr; 789*7c478bd9Sstevel@tonic-gate rp->r_pc = args->entry; 790*7c478bd9Sstevel@tonic-gate rp->r_npc = args->entry + 4; 791*7c478bd9Sstevel@tonic-gate rp->r_y = 0; 792*7c478bd9Sstevel@tonic-gate curthread->t_post_sys = 1; 793*7c478bd9Sstevel@tonic-gate lwp->lwp_eosys = JUSTRETURN; 794*7c478bd9Sstevel@tonic-gate lwp->lwp_pcb.pcb_trap0addr = NULL; /* no trap 0 handler */ 795*7c478bd9Sstevel@tonic-gate /* 796*7c478bd9Sstevel@tonic-gate * Clear the fixalignment flag 797*7c478bd9Sstevel@tonic-gate */ 798*7c478bd9Sstevel@tonic-gate p->p_fixalignment = 0; 799*7c478bd9Sstevel@tonic-gate 800*7c478bd9Sstevel@tonic-gate /* 801*7c478bd9Sstevel@tonic-gate * Throw out old user windows, init window buf. 802*7c478bd9Sstevel@tonic-gate */ 803*7c478bd9Sstevel@tonic-gate trash_user_windows(); 804*7c478bd9Sstevel@tonic-gate 805*7c478bd9Sstevel@tonic-gate if (p->p_model == DATAMODEL_LP64 && 806*7c478bd9Sstevel@tonic-gate mpcb->mpcb_wstate != WSTATE_USER64) { 807*7c478bd9Sstevel@tonic-gate ASSERT(mpcb->mpcb_wbcnt == 0); 808*7c478bd9Sstevel@tonic-gate kmem_free(mpcb->mpcb_wbuf, MAXWIN * sizeof (struct rwindow32)); 809*7c478bd9Sstevel@tonic-gate mpcb->mpcb_wbuf = kmem_alloc(MAXWIN * 810*7c478bd9Sstevel@tonic-gate sizeof (struct rwindow64), KM_SLEEP); 811*7c478bd9Sstevel@tonic-gate ASSERT(((uintptr_t)mpcb->mpcb_wbuf & 7) == 0); 812*7c478bd9Sstevel@tonic-gate mpcb->mpcb_wstate = WSTATE_USER64; 813*7c478bd9Sstevel@tonic-gate } else if (p->p_model == DATAMODEL_ILP32 && 814*7c478bd9Sstevel@tonic-gate mpcb->mpcb_wstate != WSTATE_USER32) { 815*7c478bd9Sstevel@tonic-gate ASSERT(mpcb->mpcb_wbcnt == 0); 816*7c478bd9Sstevel@tonic-gate kmem_free(mpcb->mpcb_wbuf, MAXWIN * sizeof (struct rwindow64)); 817*7c478bd9Sstevel@tonic-gate mpcb->mpcb_wbuf = kmem_alloc(MAXWIN * 818*7c478bd9Sstevel@tonic-gate sizeof (struct rwindow32), KM_SLEEP); 819*7c478bd9Sstevel@tonic-gate mpcb->mpcb_wstate = WSTATE_USER32; 820*7c478bd9Sstevel@tonic-gate } 821*7c478bd9Sstevel@tonic-gate mpcb->mpcb_pa = va_to_pa(mpcb); 822*7c478bd9Sstevel@tonic-gate mpcb->mpcb_wbuf_pa = va_to_pa(mpcb->mpcb_wbuf); 823*7c478bd9Sstevel@tonic-gate 824*7c478bd9Sstevel@tonic-gate /* 825*7c478bd9Sstevel@tonic-gate * Here we initialize minimal fpu state. 826*7c478bd9Sstevel@tonic-gate * The rest is done at the first floating 827*7c478bd9Sstevel@tonic-gate * point instruction that a process executes 828*7c478bd9Sstevel@tonic-gate * or by the lib_psr memcpy routines. 829*7c478bd9Sstevel@tonic-gate */ 830*7c478bd9Sstevel@tonic-gate if (fpu_exists) { 831*7c478bd9Sstevel@tonic-gate extern void _fp_write_fprs(unsigned); 832*7c478bd9Sstevel@tonic-gate _fp_write_fprs(0); 833*7c478bd9Sstevel@tonic-gate } 834*7c478bd9Sstevel@tonic-gate fpp->fpu_en = 0; 835*7c478bd9Sstevel@tonic-gate fpp->fpu_fprs = 0; 836*7c478bd9Sstevel@tonic-gate } 837*7c478bd9Sstevel@tonic-gate 838*7c478bd9Sstevel@tonic-gate void 839*7c478bd9Sstevel@tonic-gate lwp_swapin(kthread_t *tp) 840*7c478bd9Sstevel@tonic-gate { 841*7c478bd9Sstevel@tonic-gate struct machpcb *mpcb = lwptompcb(ttolwp(tp)); 842*7c478bd9Sstevel@tonic-gate 843*7c478bd9Sstevel@tonic-gate mpcb->mpcb_pa = va_to_pa(mpcb); 844*7c478bd9Sstevel@tonic-gate mpcb->mpcb_wbuf_pa = va_to_pa(mpcb->mpcb_wbuf); 845*7c478bd9Sstevel@tonic-gate } 846*7c478bd9Sstevel@tonic-gate 847*7c478bd9Sstevel@tonic-gate /* 848*7c478bd9Sstevel@tonic-gate * Construct the execution environment for the user's signal 849*7c478bd9Sstevel@tonic-gate * handler and arrange for control to be given to it on return 850*7c478bd9Sstevel@tonic-gate * to userland. The library code now calls setcontext() to 851*7c478bd9Sstevel@tonic-gate * clean up after the signal handler, so sigret() is no longer 852*7c478bd9Sstevel@tonic-gate * needed. 853*7c478bd9Sstevel@tonic-gate */ 854*7c478bd9Sstevel@tonic-gate int 855*7c478bd9Sstevel@tonic-gate sendsig(int sig, k_siginfo_t *sip, void (*hdlr)()) 856*7c478bd9Sstevel@tonic-gate { 857*7c478bd9Sstevel@tonic-gate /* 858*7c478bd9Sstevel@tonic-gate * 'volatile' is needed to ensure that values are 859*7c478bd9Sstevel@tonic-gate * correct on the error return from on_fault(). 860*7c478bd9Sstevel@tonic-gate */ 861*7c478bd9Sstevel@tonic-gate volatile int minstacksz; /* min stack required to catch signal */ 862*7c478bd9Sstevel@tonic-gate int newstack = 0; /* if true, switching to altstack */ 863*7c478bd9Sstevel@tonic-gate label_t ljb; 864*7c478bd9Sstevel@tonic-gate caddr_t sp; 865*7c478bd9Sstevel@tonic-gate struct regs *volatile rp; 866*7c478bd9Sstevel@tonic-gate klwp_t *lwp = ttolwp(curthread); 867*7c478bd9Sstevel@tonic-gate proc_t *volatile p = ttoproc(curthread); 868*7c478bd9Sstevel@tonic-gate int fpq_size = 0; 869*7c478bd9Sstevel@tonic-gate struct sigframe { 870*7c478bd9Sstevel@tonic-gate struct frame frwin; 871*7c478bd9Sstevel@tonic-gate ucontext_t uc; 872*7c478bd9Sstevel@tonic-gate }; 873*7c478bd9Sstevel@tonic-gate siginfo_t *sip_addr; 874*7c478bd9Sstevel@tonic-gate struct sigframe *volatile fp; 875*7c478bd9Sstevel@tonic-gate ucontext_t *volatile tuc = NULL; 876*7c478bd9Sstevel@tonic-gate char *volatile xregs = NULL; 877*7c478bd9Sstevel@tonic-gate volatile size_t xregs_size = 0; 878*7c478bd9Sstevel@tonic-gate gwindows_t *volatile gwp = NULL; 879*7c478bd9Sstevel@tonic-gate volatile int gwin_size = 0; 880*7c478bd9Sstevel@tonic-gate kfpu_t *fpp; 881*7c478bd9Sstevel@tonic-gate struct machpcb *mpcb; 882*7c478bd9Sstevel@tonic-gate volatile int watched = 0; 883*7c478bd9Sstevel@tonic-gate volatile int watched2 = 0; 884*7c478bd9Sstevel@tonic-gate caddr_t tos; 885*7c478bd9Sstevel@tonic-gate 886*7c478bd9Sstevel@tonic-gate /* 887*7c478bd9Sstevel@tonic-gate * Make sure the current last user window has been flushed to 888*7c478bd9Sstevel@tonic-gate * the stack save area before we change the sp. 889*7c478bd9Sstevel@tonic-gate * Restore register window if a debugger modified it. 890*7c478bd9Sstevel@tonic-gate */ 891*7c478bd9Sstevel@tonic-gate (void) flush_user_windows_to_stack(NULL); 892*7c478bd9Sstevel@tonic-gate if (lwp->lwp_pcb.pcb_xregstat != XREGNONE) 893*7c478bd9Sstevel@tonic-gate xregrestore(lwp, 0); 894*7c478bd9Sstevel@tonic-gate 895*7c478bd9Sstevel@tonic-gate mpcb = lwptompcb(lwp); 896*7c478bd9Sstevel@tonic-gate rp = lwptoregs(lwp); 897*7c478bd9Sstevel@tonic-gate 898*7c478bd9Sstevel@tonic-gate /* 899*7c478bd9Sstevel@tonic-gate * Clear the watchpoint return stack pointers. 900*7c478bd9Sstevel@tonic-gate */ 901*7c478bd9Sstevel@tonic-gate mpcb->mpcb_rsp[0] = NULL; 902*7c478bd9Sstevel@tonic-gate mpcb->mpcb_rsp[1] = NULL; 903*7c478bd9Sstevel@tonic-gate 904*7c478bd9Sstevel@tonic-gate minstacksz = sizeof (struct sigframe); 905*7c478bd9Sstevel@tonic-gate 906*7c478bd9Sstevel@tonic-gate /* 907*7c478bd9Sstevel@tonic-gate * We know that sizeof (siginfo_t) is stack-aligned: 908*7c478bd9Sstevel@tonic-gate * 128 bytes for ILP32, 256 bytes for LP64. 909*7c478bd9Sstevel@tonic-gate */ 910*7c478bd9Sstevel@tonic-gate if (sip != NULL) 911*7c478bd9Sstevel@tonic-gate minstacksz += sizeof (siginfo_t); 912*7c478bd9Sstevel@tonic-gate 913*7c478bd9Sstevel@tonic-gate /* 914*7c478bd9Sstevel@tonic-gate * These two fields are pointed to by ABI structures and may 915*7c478bd9Sstevel@tonic-gate * be of arbitrary length. Size them now so we know how big 916*7c478bd9Sstevel@tonic-gate * the signal frame has to be. 917*7c478bd9Sstevel@tonic-gate */ 918*7c478bd9Sstevel@tonic-gate fpp = lwptofpu(lwp); 919*7c478bd9Sstevel@tonic-gate fpp->fpu_fprs = _fp_read_fprs(); 920*7c478bd9Sstevel@tonic-gate if ((fpp->fpu_en) || (fpp->fpu_fprs & FPRS_FEF)) { 921*7c478bd9Sstevel@tonic-gate fpq_size = fpp->fpu_q_entrysize * fpp->fpu_qcnt; 922*7c478bd9Sstevel@tonic-gate minstacksz += SA(fpq_size); 923*7c478bd9Sstevel@tonic-gate } 924*7c478bd9Sstevel@tonic-gate 925*7c478bd9Sstevel@tonic-gate mpcb = lwptompcb(lwp); 926*7c478bd9Sstevel@tonic-gate if (mpcb->mpcb_wbcnt != 0) { 927*7c478bd9Sstevel@tonic-gate gwin_size = (mpcb->mpcb_wbcnt * sizeof (struct rwindow)) + 928*7c478bd9Sstevel@tonic-gate (SPARC_MAXREGWINDOW * sizeof (caddr_t)) + sizeof (long); 929*7c478bd9Sstevel@tonic-gate minstacksz += SA(gwin_size); 930*7c478bd9Sstevel@tonic-gate } 931*7c478bd9Sstevel@tonic-gate 932*7c478bd9Sstevel@tonic-gate /* 933*7c478bd9Sstevel@tonic-gate * Extra registers, if support by this platform, may be of arbitrary 934*7c478bd9Sstevel@tonic-gate * length. Size them now so we know how big the signal frame has to be. 935*7c478bd9Sstevel@tonic-gate * For sparcv9 _LP64 user programs, use asrs instead of the xregs. 936*7c478bd9Sstevel@tonic-gate */ 937*7c478bd9Sstevel@tonic-gate minstacksz += SA(xregs_size); 938*7c478bd9Sstevel@tonic-gate 939*7c478bd9Sstevel@tonic-gate /* 940*7c478bd9Sstevel@tonic-gate * Figure out whether we will be handling this signal on 941*7c478bd9Sstevel@tonic-gate * an alternate stack specified by the user. Then allocate 942*7c478bd9Sstevel@tonic-gate * and validate the stack requirements for the signal handler 943*7c478bd9Sstevel@tonic-gate * context. on_fault will catch any faults. 944*7c478bd9Sstevel@tonic-gate */ 945*7c478bd9Sstevel@tonic-gate newstack = (sigismember(&u.u_sigonstack, sig) && 946*7c478bd9Sstevel@tonic-gate !(lwp->lwp_sigaltstack.ss_flags & (SS_ONSTACK|SS_DISABLE))); 947*7c478bd9Sstevel@tonic-gate 948*7c478bd9Sstevel@tonic-gate tos = (caddr_t)rp->r_sp + STACK_BIAS; 949*7c478bd9Sstevel@tonic-gate if (newstack != 0) { 950*7c478bd9Sstevel@tonic-gate fp = (struct sigframe *) 951*7c478bd9Sstevel@tonic-gate (SA((uintptr_t)lwp->lwp_sigaltstack.ss_sp) + 952*7c478bd9Sstevel@tonic-gate SA((int)lwp->lwp_sigaltstack.ss_size) - STACK_ALIGN - 953*7c478bd9Sstevel@tonic-gate SA(minstacksz)); 954*7c478bd9Sstevel@tonic-gate } else { 955*7c478bd9Sstevel@tonic-gate /* 956*7c478bd9Sstevel@tonic-gate * If we were unable to flush all register windows to 957*7c478bd9Sstevel@tonic-gate * the stack and we are not now on an alternate stack, 958*7c478bd9Sstevel@tonic-gate * just dump core with a SIGSEGV back in psig(). 959*7c478bd9Sstevel@tonic-gate */ 960*7c478bd9Sstevel@tonic-gate if (sig == SIGSEGV && 961*7c478bd9Sstevel@tonic-gate mpcb->mpcb_wbcnt != 0 && 962*7c478bd9Sstevel@tonic-gate !(lwp->lwp_sigaltstack.ss_flags & SS_ONSTACK)) 963*7c478bd9Sstevel@tonic-gate return (0); 964*7c478bd9Sstevel@tonic-gate fp = (struct sigframe *)(tos - SA(minstacksz)); 965*7c478bd9Sstevel@tonic-gate /* 966*7c478bd9Sstevel@tonic-gate * Could call grow here, but stack growth now handled below 967*7c478bd9Sstevel@tonic-gate * in code protected by on_fault(). 968*7c478bd9Sstevel@tonic-gate */ 969*7c478bd9Sstevel@tonic-gate } 970*7c478bd9Sstevel@tonic-gate sp = (caddr_t)fp + sizeof (struct sigframe); 971*7c478bd9Sstevel@tonic-gate 972*7c478bd9Sstevel@tonic-gate /* 973*7c478bd9Sstevel@tonic-gate * Make sure process hasn't trashed its stack. 974*7c478bd9Sstevel@tonic-gate */ 975*7c478bd9Sstevel@tonic-gate if (((uintptr_t)fp & (STACK_ALIGN - 1)) != 0 || 976*7c478bd9Sstevel@tonic-gate (caddr_t)fp >= p->p_usrstack || 977*7c478bd9Sstevel@tonic-gate (caddr_t)fp + SA(minstacksz) >= p->p_usrstack) { 978*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 979*7c478bd9Sstevel@tonic-gate printf("sendsig: bad signal stack cmd=%s, pid=%d, sig=%d\n", 980*7c478bd9Sstevel@tonic-gate PTOU(p)->u_comm, p->p_pid, sig); 981*7c478bd9Sstevel@tonic-gate printf("sigsp = 0x%p, action = 0x%p, upc = 0x%lx\n", 982*7c478bd9Sstevel@tonic-gate (void *)fp, (void *)hdlr, rp->r_pc); 983*7c478bd9Sstevel@tonic-gate 984*7c478bd9Sstevel@tonic-gate if (((uintptr_t)fp & (STACK_ALIGN - 1)) != 0) 985*7c478bd9Sstevel@tonic-gate printf("bad stack alignment\n"); 986*7c478bd9Sstevel@tonic-gate else 987*7c478bd9Sstevel@tonic-gate printf("fp above USRSTACK\n"); 988*7c478bd9Sstevel@tonic-gate #endif 989*7c478bd9Sstevel@tonic-gate return (0); 990*7c478bd9Sstevel@tonic-gate } 991*7c478bd9Sstevel@tonic-gate 992*7c478bd9Sstevel@tonic-gate watched = watch_disable_addr((caddr_t)fp, SA(minstacksz), S_WRITE); 993*7c478bd9Sstevel@tonic-gate if (on_fault(&ljb)) 994*7c478bd9Sstevel@tonic-gate goto badstack; 995*7c478bd9Sstevel@tonic-gate 996*7c478bd9Sstevel@tonic-gate tuc = kmem_alloc(sizeof (ucontext_t), KM_SLEEP); 997*7c478bd9Sstevel@tonic-gate savecontext(tuc, lwp->lwp_sigoldmask); 998*7c478bd9Sstevel@tonic-gate 999*7c478bd9Sstevel@tonic-gate /* 1000*7c478bd9Sstevel@tonic-gate * save extra register state if it exists 1001*7c478bd9Sstevel@tonic-gate */ 1002*7c478bd9Sstevel@tonic-gate if (xregs_size != 0) { 1003*7c478bd9Sstevel@tonic-gate xregs_setptr(lwp, tuc, sp); 1004*7c478bd9Sstevel@tonic-gate xregs = kmem_alloc(xregs_size, KM_SLEEP); 1005*7c478bd9Sstevel@tonic-gate xregs_get(lwp, xregs); 1006*7c478bd9Sstevel@tonic-gate copyout_noerr(xregs, sp, xregs_size); 1007*7c478bd9Sstevel@tonic-gate kmem_free(xregs, xregs_size); 1008*7c478bd9Sstevel@tonic-gate xregs = NULL; 1009*7c478bd9Sstevel@tonic-gate sp += SA(xregs_size); 1010*7c478bd9Sstevel@tonic-gate } 1011*7c478bd9Sstevel@tonic-gate 1012*7c478bd9Sstevel@tonic-gate copyout_noerr(tuc, &fp->uc, sizeof (*tuc)); 1013*7c478bd9Sstevel@tonic-gate kmem_free(tuc, sizeof (*tuc)); 1014*7c478bd9Sstevel@tonic-gate tuc = NULL; 1015*7c478bd9Sstevel@tonic-gate 1016*7c478bd9Sstevel@tonic-gate if (sip != NULL) { 1017*7c478bd9Sstevel@tonic-gate zoneid_t zoneid; 1018*7c478bd9Sstevel@tonic-gate 1019*7c478bd9Sstevel@tonic-gate uzero(sp, sizeof (siginfo_t)); 1020*7c478bd9Sstevel@tonic-gate if (SI_FROMUSER(sip) && 1021*7c478bd9Sstevel@tonic-gate (zoneid = p->p_zone->zone_id) != GLOBAL_ZONEID && 1022*7c478bd9Sstevel@tonic-gate zoneid != sip->si_zoneid) { 1023*7c478bd9Sstevel@tonic-gate k_siginfo_t sani_sip = *sip; 1024*7c478bd9Sstevel@tonic-gate sani_sip.si_pid = p->p_zone->zone_zsched->p_pid; 1025*7c478bd9Sstevel@tonic-gate sani_sip.si_uid = 0; 1026*7c478bd9Sstevel@tonic-gate sani_sip.si_ctid = -1; 1027*7c478bd9Sstevel@tonic-gate sani_sip.si_zoneid = zoneid; 1028*7c478bd9Sstevel@tonic-gate copyout_noerr(&sani_sip, sp, sizeof (sani_sip)); 1029*7c478bd9Sstevel@tonic-gate } else { 1030*7c478bd9Sstevel@tonic-gate copyout_noerr(sip, sp, sizeof (*sip)); 1031*7c478bd9Sstevel@tonic-gate } 1032*7c478bd9Sstevel@tonic-gate sip_addr = (siginfo_t *)sp; 1033*7c478bd9Sstevel@tonic-gate sp += sizeof (siginfo_t); 1034*7c478bd9Sstevel@tonic-gate 1035*7c478bd9Sstevel@tonic-gate if (sig == SIGPROF && 1036*7c478bd9Sstevel@tonic-gate curthread->t_rprof != NULL && 1037*7c478bd9Sstevel@tonic-gate curthread->t_rprof->rp_anystate) { 1038*7c478bd9Sstevel@tonic-gate /* 1039*7c478bd9Sstevel@tonic-gate * We stand on our head to deal with 1040*7c478bd9Sstevel@tonic-gate * the real time profiling signal. 1041*7c478bd9Sstevel@tonic-gate * Fill in the stuff that doesn't fit 1042*7c478bd9Sstevel@tonic-gate * in a normal k_siginfo structure. 1043*7c478bd9Sstevel@tonic-gate */ 1044*7c478bd9Sstevel@tonic-gate int i = sip->si_nsysarg; 1045*7c478bd9Sstevel@tonic-gate while (--i >= 0) { 1046*7c478bd9Sstevel@tonic-gate sulword_noerr( 1047*7c478bd9Sstevel@tonic-gate (ulong_t *)&sip_addr->si_sysarg[i], 1048*7c478bd9Sstevel@tonic-gate (ulong_t)lwp->lwp_arg[i]); 1049*7c478bd9Sstevel@tonic-gate } 1050*7c478bd9Sstevel@tonic-gate copyout_noerr(curthread->t_rprof->rp_state, 1051*7c478bd9Sstevel@tonic-gate sip_addr->si_mstate, 1052*7c478bd9Sstevel@tonic-gate sizeof (curthread->t_rprof->rp_state)); 1053*7c478bd9Sstevel@tonic-gate } 1054*7c478bd9Sstevel@tonic-gate } else { 1055*7c478bd9Sstevel@tonic-gate sip_addr = (siginfo_t *)NULL; 1056*7c478bd9Sstevel@tonic-gate } 1057*7c478bd9Sstevel@tonic-gate 1058*7c478bd9Sstevel@tonic-gate /* 1059*7c478bd9Sstevel@tonic-gate * When flush_user_windows_to_stack() can't save all the 1060*7c478bd9Sstevel@tonic-gate * windows to the stack, it puts them in the lwp's pcb. 1061*7c478bd9Sstevel@tonic-gate */ 1062*7c478bd9Sstevel@tonic-gate if (gwin_size != 0) { 1063*7c478bd9Sstevel@tonic-gate gwp = kmem_alloc(gwin_size, KM_SLEEP); 1064*7c478bd9Sstevel@tonic-gate getgwins(lwp, gwp); 1065*7c478bd9Sstevel@tonic-gate sulword_noerr(&fp->uc.uc_mcontext.gwins, (ulong_t)sp); 1066*7c478bd9Sstevel@tonic-gate copyout_noerr(gwp, sp, gwin_size); 1067*7c478bd9Sstevel@tonic-gate kmem_free(gwp, gwin_size); 1068*7c478bd9Sstevel@tonic-gate gwp = NULL; 1069*7c478bd9Sstevel@tonic-gate sp += SA(gwin_size); 1070*7c478bd9Sstevel@tonic-gate } else 1071*7c478bd9Sstevel@tonic-gate sulword_noerr(&fp->uc.uc_mcontext.gwins, (ulong_t)NULL); 1072*7c478bd9Sstevel@tonic-gate 1073*7c478bd9Sstevel@tonic-gate if (fpq_size != 0) { 1074*7c478bd9Sstevel@tonic-gate struct fq *fqp = (struct fq *)sp; 1075*7c478bd9Sstevel@tonic-gate sulword_noerr(&fp->uc.uc_mcontext.fpregs.fpu_q, (ulong_t)fqp); 1076*7c478bd9Sstevel@tonic-gate copyout_noerr(mpcb->mpcb_fpu_q, fqp, fpq_size); 1077*7c478bd9Sstevel@tonic-gate 1078*7c478bd9Sstevel@tonic-gate /* 1079*7c478bd9Sstevel@tonic-gate * forget the fp queue so that the signal handler can run 1080*7c478bd9Sstevel@tonic-gate * without being harrassed--it will do a setcontext that will 1081*7c478bd9Sstevel@tonic-gate * re-establish the queue if there still is one 1082*7c478bd9Sstevel@tonic-gate * 1083*7c478bd9Sstevel@tonic-gate * NOTE: fp_runq() relies on the qcnt field being zeroed here 1084*7c478bd9Sstevel@tonic-gate * to terminate its processing of the queue after signal 1085*7c478bd9Sstevel@tonic-gate * delivery. 1086*7c478bd9Sstevel@tonic-gate */ 1087*7c478bd9Sstevel@tonic-gate mpcb->mpcb_fpu->fpu_qcnt = 0; 1088*7c478bd9Sstevel@tonic-gate sp += SA(fpq_size); 1089*7c478bd9Sstevel@tonic-gate 1090*7c478bd9Sstevel@tonic-gate /* Also, syscall needs to know about this */ 1091*7c478bd9Sstevel@tonic-gate mpcb->mpcb_flags |= FP_TRAPPED; 1092*7c478bd9Sstevel@tonic-gate 1093*7c478bd9Sstevel@tonic-gate } else { 1094*7c478bd9Sstevel@tonic-gate sulword_noerr(&fp->uc.uc_mcontext.fpregs.fpu_q, (ulong_t)NULL); 1095*7c478bd9Sstevel@tonic-gate suword8_noerr(&fp->uc.uc_mcontext.fpregs.fpu_qcnt, 0); 1096*7c478bd9Sstevel@tonic-gate } 1097*7c478bd9Sstevel@tonic-gate 1098*7c478bd9Sstevel@tonic-gate 1099*7c478bd9Sstevel@tonic-gate /* 1100*7c478bd9Sstevel@tonic-gate * Since we flushed the user's windows and we are changing his 1101*7c478bd9Sstevel@tonic-gate * stack pointer, the window that the user will return to will 1102*7c478bd9Sstevel@tonic-gate * be restored from the save area in the frame we are setting up. 1103*7c478bd9Sstevel@tonic-gate * We copy in save area for old stack pointer so that debuggers 1104*7c478bd9Sstevel@tonic-gate * can do a proper stack backtrace from the signal handler. 1105*7c478bd9Sstevel@tonic-gate */ 1106*7c478bd9Sstevel@tonic-gate if (mpcb->mpcb_wbcnt == 0) { 1107*7c478bd9Sstevel@tonic-gate watched2 = watch_disable_addr(tos, sizeof (struct rwindow), 1108*7c478bd9Sstevel@tonic-gate S_READ); 1109*7c478bd9Sstevel@tonic-gate ucopy(tos, &fp->frwin, sizeof (struct rwindow)); 1110*7c478bd9Sstevel@tonic-gate } 1111*7c478bd9Sstevel@tonic-gate 1112*7c478bd9Sstevel@tonic-gate lwp->lwp_oldcontext = (uintptr_t)&fp->uc; 1113*7c478bd9Sstevel@tonic-gate 1114*7c478bd9Sstevel@tonic-gate if (newstack != 0) { 1115*7c478bd9Sstevel@tonic-gate lwp->lwp_sigaltstack.ss_flags |= SS_ONSTACK; 1116*7c478bd9Sstevel@tonic-gate 1117*7c478bd9Sstevel@tonic-gate if (lwp->lwp_ustack) { 1118*7c478bd9Sstevel@tonic-gate copyout_noerr(&lwp->lwp_sigaltstack, 1119*7c478bd9Sstevel@tonic-gate (stack_t *)lwp->lwp_ustack, sizeof (stack_t)); 1120*7c478bd9Sstevel@tonic-gate } 1121*7c478bd9Sstevel@tonic-gate } 1122*7c478bd9Sstevel@tonic-gate 1123*7c478bd9Sstevel@tonic-gate no_fault(); 1124*7c478bd9Sstevel@tonic-gate mpcb->mpcb_wbcnt = 0; /* let user go on */ 1125*7c478bd9Sstevel@tonic-gate 1126*7c478bd9Sstevel@tonic-gate if (watched2) 1127*7c478bd9Sstevel@tonic-gate watch_enable_addr(tos, sizeof (struct rwindow), S_READ); 1128*7c478bd9Sstevel@tonic-gate if (watched) 1129*7c478bd9Sstevel@tonic-gate watch_enable_addr((caddr_t)fp, SA(minstacksz), S_WRITE); 1130*7c478bd9Sstevel@tonic-gate 1131*7c478bd9Sstevel@tonic-gate /* 1132*7c478bd9Sstevel@tonic-gate * Set up user registers for execution of signal handler. 1133*7c478bd9Sstevel@tonic-gate */ 1134*7c478bd9Sstevel@tonic-gate rp->r_sp = (uintptr_t)fp - STACK_BIAS; 1135*7c478bd9Sstevel@tonic-gate rp->r_pc = (uintptr_t)hdlr; 1136*7c478bd9Sstevel@tonic-gate rp->r_npc = (uintptr_t)hdlr + 4; 1137*7c478bd9Sstevel@tonic-gate /* make sure %asi is ASI_PNF */ 1138*7c478bd9Sstevel@tonic-gate rp->r_tstate &= ~((uint64_t)TSTATE_ASI_MASK << TSTATE_ASI_SHIFT); 1139*7c478bd9Sstevel@tonic-gate rp->r_tstate |= ((uint64_t)ASI_PNF << TSTATE_ASI_SHIFT); 1140*7c478bd9Sstevel@tonic-gate rp->r_o0 = sig; 1141*7c478bd9Sstevel@tonic-gate rp->r_o1 = (uintptr_t)sip_addr; 1142*7c478bd9Sstevel@tonic-gate rp->r_o2 = (uintptr_t)&fp->uc; 1143*7c478bd9Sstevel@tonic-gate /* 1144*7c478bd9Sstevel@tonic-gate * Don't set lwp_eosys here. sendsig() is called via psig() after 1145*7c478bd9Sstevel@tonic-gate * lwp_eosys is handled, so setting it here would affect the next 1146*7c478bd9Sstevel@tonic-gate * system call. 1147*7c478bd9Sstevel@tonic-gate */ 1148*7c478bd9Sstevel@tonic-gate return (1); 1149*7c478bd9Sstevel@tonic-gate 1150*7c478bd9Sstevel@tonic-gate badstack: 1151*7c478bd9Sstevel@tonic-gate no_fault(); 1152*7c478bd9Sstevel@tonic-gate if (watched2) 1153*7c478bd9Sstevel@tonic-gate watch_enable_addr(tos, sizeof (struct rwindow), S_READ); 1154*7c478bd9Sstevel@tonic-gate if (watched) 1155*7c478bd9Sstevel@tonic-gate watch_enable_addr((caddr_t)fp, SA(minstacksz), S_WRITE); 1156*7c478bd9Sstevel@tonic-gate if (tuc) 1157*7c478bd9Sstevel@tonic-gate kmem_free(tuc, sizeof (ucontext_t)); 1158*7c478bd9Sstevel@tonic-gate if (xregs) 1159*7c478bd9Sstevel@tonic-gate kmem_free(xregs, xregs_size); 1160*7c478bd9Sstevel@tonic-gate if (gwp) 1161*7c478bd9Sstevel@tonic-gate kmem_free(gwp, gwin_size); 1162*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 1163*7c478bd9Sstevel@tonic-gate printf("sendsig: bad signal stack cmd=%s, pid=%d, sig=%d\n", 1164*7c478bd9Sstevel@tonic-gate PTOU(p)->u_comm, p->p_pid, sig); 1165*7c478bd9Sstevel@tonic-gate printf("on fault, sigsp = %p, action = %p, upc = 0x%lx\n", 1166*7c478bd9Sstevel@tonic-gate (void *)fp, (void *)hdlr, rp->r_pc); 1167*7c478bd9Sstevel@tonic-gate #endif 1168*7c478bd9Sstevel@tonic-gate return (0); 1169*7c478bd9Sstevel@tonic-gate } 1170*7c478bd9Sstevel@tonic-gate 1171*7c478bd9Sstevel@tonic-gate 1172*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 1173*7c478bd9Sstevel@tonic-gate 1174*7c478bd9Sstevel@tonic-gate /* 1175*7c478bd9Sstevel@tonic-gate * Construct the execution environment for the user's signal 1176*7c478bd9Sstevel@tonic-gate * handler and arrange for control to be given to it on return 1177*7c478bd9Sstevel@tonic-gate * to userland. The library code now calls setcontext() to 1178*7c478bd9Sstevel@tonic-gate * clean up after the signal handler, so sigret() is no longer 1179*7c478bd9Sstevel@tonic-gate * needed. 1180*7c478bd9Sstevel@tonic-gate */ 1181*7c478bd9Sstevel@tonic-gate int 1182*7c478bd9Sstevel@tonic-gate sendsig32(int sig, k_siginfo_t *sip, void (*hdlr)()) 1183*7c478bd9Sstevel@tonic-gate { 1184*7c478bd9Sstevel@tonic-gate /* 1185*7c478bd9Sstevel@tonic-gate * 'volatile' is needed to ensure that values are 1186*7c478bd9Sstevel@tonic-gate * correct on the error return from on_fault(). 1187*7c478bd9Sstevel@tonic-gate */ 1188*7c478bd9Sstevel@tonic-gate volatile int minstacksz; /* min stack required to catch signal */ 1189*7c478bd9Sstevel@tonic-gate int newstack = 0; /* if true, switching to altstack */ 1190*7c478bd9Sstevel@tonic-gate label_t ljb; 1191*7c478bd9Sstevel@tonic-gate caddr_t sp; 1192*7c478bd9Sstevel@tonic-gate struct regs *volatile rp; 1193*7c478bd9Sstevel@tonic-gate klwp_t *lwp = ttolwp(curthread); 1194*7c478bd9Sstevel@tonic-gate proc_t *volatile p = ttoproc(curthread); 1195*7c478bd9Sstevel@tonic-gate struct fq32 fpu_q[MAXFPQ]; /* to hold floating queue */ 1196*7c478bd9Sstevel@tonic-gate struct fq32 *dfq = NULL; 1197*7c478bd9Sstevel@tonic-gate size_t fpq_size = 0; 1198*7c478bd9Sstevel@tonic-gate struct sigframe32 { 1199*7c478bd9Sstevel@tonic-gate struct frame32 frwin; 1200*7c478bd9Sstevel@tonic-gate ucontext32_t uc; 1201*7c478bd9Sstevel@tonic-gate }; 1202*7c478bd9Sstevel@tonic-gate struct sigframe32 *volatile fp; 1203*7c478bd9Sstevel@tonic-gate siginfo32_t *sip_addr; 1204*7c478bd9Sstevel@tonic-gate ucontext32_t *volatile tuc = NULL; 1205*7c478bd9Sstevel@tonic-gate char *volatile xregs = NULL; 1206*7c478bd9Sstevel@tonic-gate volatile int xregs_size = 0; 1207*7c478bd9Sstevel@tonic-gate gwindows32_t *volatile gwp = NULL; 1208*7c478bd9Sstevel@tonic-gate volatile size_t gwin_size = 0; 1209*7c478bd9Sstevel@tonic-gate kfpu_t *fpp; 1210*7c478bd9Sstevel@tonic-gate struct machpcb *mpcb; 1211*7c478bd9Sstevel@tonic-gate volatile int watched = 0; 1212*7c478bd9Sstevel@tonic-gate volatile int watched2 = 0; 1213*7c478bd9Sstevel@tonic-gate caddr_t tos; 1214*7c478bd9Sstevel@tonic-gate 1215*7c478bd9Sstevel@tonic-gate /* 1216*7c478bd9Sstevel@tonic-gate * Make sure the current last user window has been flushed to 1217*7c478bd9Sstevel@tonic-gate * the stack save area before we change the sp. 1218*7c478bd9Sstevel@tonic-gate * Restore register window if a debugger modified it. 1219*7c478bd9Sstevel@tonic-gate */ 1220*7c478bd9Sstevel@tonic-gate (void) flush_user_windows_to_stack(NULL); 1221*7c478bd9Sstevel@tonic-gate if (lwp->lwp_pcb.pcb_xregstat != XREGNONE) 1222*7c478bd9Sstevel@tonic-gate xregrestore(lwp, 0); 1223*7c478bd9Sstevel@tonic-gate 1224*7c478bd9Sstevel@tonic-gate mpcb = lwptompcb(lwp); 1225*7c478bd9Sstevel@tonic-gate rp = lwptoregs(lwp); 1226*7c478bd9Sstevel@tonic-gate 1227*7c478bd9Sstevel@tonic-gate /* 1228*7c478bd9Sstevel@tonic-gate * Clear the watchpoint return stack pointers. 1229*7c478bd9Sstevel@tonic-gate */ 1230*7c478bd9Sstevel@tonic-gate mpcb->mpcb_rsp[0] = NULL; 1231*7c478bd9Sstevel@tonic-gate mpcb->mpcb_rsp[1] = NULL; 1232*7c478bd9Sstevel@tonic-gate 1233*7c478bd9Sstevel@tonic-gate minstacksz = sizeof (struct sigframe32); 1234*7c478bd9Sstevel@tonic-gate 1235*7c478bd9Sstevel@tonic-gate if (sip != NULL) 1236*7c478bd9Sstevel@tonic-gate minstacksz += sizeof (siginfo32_t); 1237*7c478bd9Sstevel@tonic-gate 1238*7c478bd9Sstevel@tonic-gate /* 1239*7c478bd9Sstevel@tonic-gate * These two fields are pointed to by ABI structures and may 1240*7c478bd9Sstevel@tonic-gate * be of arbitrary length. Size them now so we know how big 1241*7c478bd9Sstevel@tonic-gate * the signal frame has to be. 1242*7c478bd9Sstevel@tonic-gate */ 1243*7c478bd9Sstevel@tonic-gate fpp = lwptofpu(lwp); 1244*7c478bd9Sstevel@tonic-gate fpp->fpu_fprs = _fp_read_fprs(); 1245*7c478bd9Sstevel@tonic-gate if ((fpp->fpu_en) || (fpp->fpu_fprs & FPRS_FEF)) { 1246*7c478bd9Sstevel@tonic-gate fpq_size = sizeof (struct fpq32) * fpp->fpu_qcnt; 1247*7c478bd9Sstevel@tonic-gate minstacksz += fpq_size; 1248*7c478bd9Sstevel@tonic-gate dfq = fpu_q; 1249*7c478bd9Sstevel@tonic-gate } 1250*7c478bd9Sstevel@tonic-gate 1251*7c478bd9Sstevel@tonic-gate mpcb = lwptompcb(lwp); 1252*7c478bd9Sstevel@tonic-gate if (mpcb->mpcb_wbcnt != 0) { 1253*7c478bd9Sstevel@tonic-gate gwin_size = (mpcb->mpcb_wbcnt * sizeof (struct rwindow32)) + 1254*7c478bd9Sstevel@tonic-gate (SPARC_MAXREGWINDOW * sizeof (caddr32_t)) + 1255*7c478bd9Sstevel@tonic-gate sizeof (int32_t); 1256*7c478bd9Sstevel@tonic-gate minstacksz += gwin_size; 1257*7c478bd9Sstevel@tonic-gate } 1258*7c478bd9Sstevel@tonic-gate 1259*7c478bd9Sstevel@tonic-gate /* 1260*7c478bd9Sstevel@tonic-gate * Extra registers, if supported by this platform, may be of arbitrary 1261*7c478bd9Sstevel@tonic-gate * length. Size them now so we know how big the signal frame has to be. 1262*7c478bd9Sstevel@tonic-gate */ 1263*7c478bd9Sstevel@tonic-gate xregs_size = xregs_getsize(p); 1264*7c478bd9Sstevel@tonic-gate minstacksz += SA32(xregs_size); 1265*7c478bd9Sstevel@tonic-gate 1266*7c478bd9Sstevel@tonic-gate /* 1267*7c478bd9Sstevel@tonic-gate * Figure out whether we will be handling this signal on 1268*7c478bd9Sstevel@tonic-gate * an alternate stack specified by the user. Then allocate 1269*7c478bd9Sstevel@tonic-gate * and validate the stack requirements for the signal handler 1270*7c478bd9Sstevel@tonic-gate * context. on_fault will catch any faults. 1271*7c478bd9Sstevel@tonic-gate */ 1272*7c478bd9Sstevel@tonic-gate newstack = (sigismember(&u.u_sigonstack, sig) && 1273*7c478bd9Sstevel@tonic-gate !(lwp->lwp_sigaltstack.ss_flags & (SS_ONSTACK|SS_DISABLE))); 1274*7c478bd9Sstevel@tonic-gate 1275*7c478bd9Sstevel@tonic-gate tos = (void *)(uint32_t)rp->r_sp; 1276*7c478bd9Sstevel@tonic-gate if (newstack != 0) { 1277*7c478bd9Sstevel@tonic-gate fp = (struct sigframe32 *) 1278*7c478bd9Sstevel@tonic-gate (SA32((uintptr_t)lwp->lwp_sigaltstack.ss_sp) + 1279*7c478bd9Sstevel@tonic-gate SA32((int)lwp->lwp_sigaltstack.ss_size) - 1280*7c478bd9Sstevel@tonic-gate STACK_ALIGN32 - 1281*7c478bd9Sstevel@tonic-gate SA32(minstacksz)); 1282*7c478bd9Sstevel@tonic-gate } else { 1283*7c478bd9Sstevel@tonic-gate /* 1284*7c478bd9Sstevel@tonic-gate * If we were unable to flush all register windows to 1285*7c478bd9Sstevel@tonic-gate * the stack and we are not now on an alternate stack, 1286*7c478bd9Sstevel@tonic-gate * just dump core with a SIGSEGV back in psig(). 1287*7c478bd9Sstevel@tonic-gate */ 1288*7c478bd9Sstevel@tonic-gate if (sig == SIGSEGV && 1289*7c478bd9Sstevel@tonic-gate mpcb->mpcb_wbcnt != 0 && 1290*7c478bd9Sstevel@tonic-gate !(lwp->lwp_sigaltstack.ss_flags & SS_ONSTACK)) 1291*7c478bd9Sstevel@tonic-gate return (0); 1292*7c478bd9Sstevel@tonic-gate fp = (struct sigframe32 *)(tos - SA32(minstacksz)); 1293*7c478bd9Sstevel@tonic-gate /* 1294*7c478bd9Sstevel@tonic-gate * Could call grow here, but stack growth now handled below 1295*7c478bd9Sstevel@tonic-gate * in code protected by on_fault(). 1296*7c478bd9Sstevel@tonic-gate */ 1297*7c478bd9Sstevel@tonic-gate } 1298*7c478bd9Sstevel@tonic-gate sp = (caddr_t)fp + sizeof (struct sigframe32); 1299*7c478bd9Sstevel@tonic-gate 1300*7c478bd9Sstevel@tonic-gate /* 1301*7c478bd9Sstevel@tonic-gate * Make sure process hasn't trashed its stack. 1302*7c478bd9Sstevel@tonic-gate */ 1303*7c478bd9Sstevel@tonic-gate if (((uintptr_t)fp & (STACK_ALIGN32 - 1)) != 0 || 1304*7c478bd9Sstevel@tonic-gate (caddr_t)fp >= p->p_usrstack || 1305*7c478bd9Sstevel@tonic-gate (caddr_t)fp + SA32(minstacksz) >= p->p_usrstack) { 1306*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 1307*7c478bd9Sstevel@tonic-gate printf("sendsig32: bad signal stack cmd=%s, pid=%d, sig=%d\n", 1308*7c478bd9Sstevel@tonic-gate PTOU(p)->u_comm, p->p_pid, sig); 1309*7c478bd9Sstevel@tonic-gate printf("sigsp = 0x%p, action = 0x%p, upc = 0x%lx\n", 1310*7c478bd9Sstevel@tonic-gate (void *)fp, (void *)hdlr, rp->r_pc); 1311*7c478bd9Sstevel@tonic-gate 1312*7c478bd9Sstevel@tonic-gate if (((uintptr_t)fp & (STACK_ALIGN32 - 1)) != 0) 1313*7c478bd9Sstevel@tonic-gate printf("bad stack alignment\n"); 1314*7c478bd9Sstevel@tonic-gate else 1315*7c478bd9Sstevel@tonic-gate printf("fp above USRSTACK32\n"); 1316*7c478bd9Sstevel@tonic-gate #endif 1317*7c478bd9Sstevel@tonic-gate return (0); 1318*7c478bd9Sstevel@tonic-gate } 1319*7c478bd9Sstevel@tonic-gate 1320*7c478bd9Sstevel@tonic-gate watched = watch_disable_addr((caddr_t)fp, SA32(minstacksz), S_WRITE); 1321*7c478bd9Sstevel@tonic-gate if (on_fault(&ljb)) 1322*7c478bd9Sstevel@tonic-gate goto badstack; 1323*7c478bd9Sstevel@tonic-gate 1324*7c478bd9Sstevel@tonic-gate tuc = kmem_alloc(sizeof (ucontext32_t), KM_SLEEP); 1325*7c478bd9Sstevel@tonic-gate savecontext32(tuc, lwp->lwp_sigoldmask, dfq); 1326*7c478bd9Sstevel@tonic-gate 1327*7c478bd9Sstevel@tonic-gate /* 1328*7c478bd9Sstevel@tonic-gate * save extra register state if it exists 1329*7c478bd9Sstevel@tonic-gate */ 1330*7c478bd9Sstevel@tonic-gate if (xregs_size != 0) { 1331*7c478bd9Sstevel@tonic-gate xregs_setptr32(lwp, tuc, (caddr32_t)sp); 1332*7c478bd9Sstevel@tonic-gate xregs = kmem_alloc(xregs_size, KM_SLEEP); 1333*7c478bd9Sstevel@tonic-gate xregs_get(lwp, xregs); 1334*7c478bd9Sstevel@tonic-gate copyout_noerr(xregs, sp, xregs_size); 1335*7c478bd9Sstevel@tonic-gate kmem_free(xregs, xregs_size); 1336*7c478bd9Sstevel@tonic-gate xregs = NULL; 1337*7c478bd9Sstevel@tonic-gate sp += SA32(xregs_size); 1338*7c478bd9Sstevel@tonic-gate } 1339*7c478bd9Sstevel@tonic-gate 1340*7c478bd9Sstevel@tonic-gate copyout_noerr(tuc, &fp->uc, sizeof (*tuc)); 1341*7c478bd9Sstevel@tonic-gate kmem_free(tuc, sizeof (*tuc)); 1342*7c478bd9Sstevel@tonic-gate tuc = NULL; 1343*7c478bd9Sstevel@tonic-gate 1344*7c478bd9Sstevel@tonic-gate if (sip != NULL) { 1345*7c478bd9Sstevel@tonic-gate siginfo32_t si32; 1346*7c478bd9Sstevel@tonic-gate zoneid_t zoneid; 1347*7c478bd9Sstevel@tonic-gate 1348*7c478bd9Sstevel@tonic-gate siginfo_kto32(sip, &si32); 1349*7c478bd9Sstevel@tonic-gate if (SI_FROMUSER(sip) && 1350*7c478bd9Sstevel@tonic-gate (zoneid = p->p_zone->zone_id) != GLOBAL_ZONEID && 1351*7c478bd9Sstevel@tonic-gate zoneid != sip->si_zoneid) { 1352*7c478bd9Sstevel@tonic-gate si32.si_pid = p->p_zone->zone_zsched->p_pid; 1353*7c478bd9Sstevel@tonic-gate si32.si_uid = 0; 1354*7c478bd9Sstevel@tonic-gate si32.si_ctid = -1; 1355*7c478bd9Sstevel@tonic-gate si32.si_zoneid = zoneid; 1356*7c478bd9Sstevel@tonic-gate } 1357*7c478bd9Sstevel@tonic-gate uzero(sp, sizeof (siginfo32_t)); 1358*7c478bd9Sstevel@tonic-gate copyout_noerr(&si32, sp, sizeof (siginfo32_t)); 1359*7c478bd9Sstevel@tonic-gate sip_addr = (siginfo32_t *)sp; 1360*7c478bd9Sstevel@tonic-gate sp += sizeof (siginfo32_t); 1361*7c478bd9Sstevel@tonic-gate 1362*7c478bd9Sstevel@tonic-gate if (sig == SIGPROF && 1363*7c478bd9Sstevel@tonic-gate curthread->t_rprof != NULL && 1364*7c478bd9Sstevel@tonic-gate curthread->t_rprof->rp_anystate) { 1365*7c478bd9Sstevel@tonic-gate /* 1366*7c478bd9Sstevel@tonic-gate * We stand on our head to deal with 1367*7c478bd9Sstevel@tonic-gate * the real time profiling signal. 1368*7c478bd9Sstevel@tonic-gate * Fill in the stuff that doesn't fit 1369*7c478bd9Sstevel@tonic-gate * in a normal k_siginfo structure. 1370*7c478bd9Sstevel@tonic-gate */ 1371*7c478bd9Sstevel@tonic-gate int i = sip->si_nsysarg; 1372*7c478bd9Sstevel@tonic-gate while (--i >= 0) { 1373*7c478bd9Sstevel@tonic-gate suword32_noerr(&sip_addr->si_sysarg[i], 1374*7c478bd9Sstevel@tonic-gate (uint32_t)lwp->lwp_arg[i]); 1375*7c478bd9Sstevel@tonic-gate } 1376*7c478bd9Sstevel@tonic-gate copyout_noerr(curthread->t_rprof->rp_state, 1377*7c478bd9Sstevel@tonic-gate sip_addr->si_mstate, 1378*7c478bd9Sstevel@tonic-gate sizeof (curthread->t_rprof->rp_state)); 1379*7c478bd9Sstevel@tonic-gate } 1380*7c478bd9Sstevel@tonic-gate } else { 1381*7c478bd9Sstevel@tonic-gate sip_addr = NULL; 1382*7c478bd9Sstevel@tonic-gate } 1383*7c478bd9Sstevel@tonic-gate 1384*7c478bd9Sstevel@tonic-gate /* 1385*7c478bd9Sstevel@tonic-gate * When flush_user_windows_to_stack() can't save all the 1386*7c478bd9Sstevel@tonic-gate * windows to the stack, it puts them in the lwp's pcb. 1387*7c478bd9Sstevel@tonic-gate */ 1388*7c478bd9Sstevel@tonic-gate if (gwin_size != 0) { 1389*7c478bd9Sstevel@tonic-gate gwp = kmem_alloc(gwin_size, KM_SLEEP); 1390*7c478bd9Sstevel@tonic-gate getgwins32(lwp, gwp); 1391*7c478bd9Sstevel@tonic-gate suword32_noerr(&fp->uc.uc_mcontext.gwins, (uint32_t)sp); 1392*7c478bd9Sstevel@tonic-gate copyout_noerr(gwp, sp, gwin_size); 1393*7c478bd9Sstevel@tonic-gate kmem_free(gwp, gwin_size); 1394*7c478bd9Sstevel@tonic-gate gwp = NULL; 1395*7c478bd9Sstevel@tonic-gate sp += gwin_size; 1396*7c478bd9Sstevel@tonic-gate } else { 1397*7c478bd9Sstevel@tonic-gate suword32_noerr(&fp->uc.uc_mcontext.gwins, (uint32_t)NULL); 1398*7c478bd9Sstevel@tonic-gate } 1399*7c478bd9Sstevel@tonic-gate 1400*7c478bd9Sstevel@tonic-gate if (fpq_size != 0) { 1401*7c478bd9Sstevel@tonic-gate /* 1402*7c478bd9Sstevel@tonic-gate * Update the (already copied out) fpu32.fpu_q pointer 1403*7c478bd9Sstevel@tonic-gate * from NULL to the 32-bit address on the user's stack 1404*7c478bd9Sstevel@tonic-gate * where we then copyout the fq32 to. 1405*7c478bd9Sstevel@tonic-gate */ 1406*7c478bd9Sstevel@tonic-gate struct fq32 *fqp = (struct fq32 *)sp; 1407*7c478bd9Sstevel@tonic-gate suword32_noerr(&fp->uc.uc_mcontext.fpregs.fpu_q, (uint32_t)fqp); 1408*7c478bd9Sstevel@tonic-gate copyout_noerr(dfq, fqp, fpq_size); 1409*7c478bd9Sstevel@tonic-gate 1410*7c478bd9Sstevel@tonic-gate /* 1411*7c478bd9Sstevel@tonic-gate * forget the fp queue so that the signal handler can run 1412*7c478bd9Sstevel@tonic-gate * without being harrassed--it will do a setcontext that will 1413*7c478bd9Sstevel@tonic-gate * re-establish the queue if there still is one 1414*7c478bd9Sstevel@tonic-gate * 1415*7c478bd9Sstevel@tonic-gate * NOTE: fp_runq() relies on the qcnt field being zeroed here 1416*7c478bd9Sstevel@tonic-gate * to terminate its processing of the queue after signal 1417*7c478bd9Sstevel@tonic-gate * delivery. 1418*7c478bd9Sstevel@tonic-gate */ 1419*7c478bd9Sstevel@tonic-gate mpcb->mpcb_fpu->fpu_qcnt = 0; 1420*7c478bd9Sstevel@tonic-gate sp += fpq_size; 1421*7c478bd9Sstevel@tonic-gate 1422*7c478bd9Sstevel@tonic-gate /* Also, syscall needs to know about this */ 1423*7c478bd9Sstevel@tonic-gate mpcb->mpcb_flags |= FP_TRAPPED; 1424*7c478bd9Sstevel@tonic-gate 1425*7c478bd9Sstevel@tonic-gate } else { 1426*7c478bd9Sstevel@tonic-gate suword32_noerr(&fp->uc.uc_mcontext.fpregs.fpu_q, 1427*7c478bd9Sstevel@tonic-gate (uint32_t)NULL); 1428*7c478bd9Sstevel@tonic-gate suword8_noerr(&fp->uc.uc_mcontext.fpregs.fpu_qcnt, 0); 1429*7c478bd9Sstevel@tonic-gate } 1430*7c478bd9Sstevel@tonic-gate 1431*7c478bd9Sstevel@tonic-gate 1432*7c478bd9Sstevel@tonic-gate /* 1433*7c478bd9Sstevel@tonic-gate * Since we flushed the user's windows and we are changing his 1434*7c478bd9Sstevel@tonic-gate * stack pointer, the window that the user will return to will 1435*7c478bd9Sstevel@tonic-gate * be restored from the save area in the frame we are setting up. 1436*7c478bd9Sstevel@tonic-gate * We copy in save area for old stack pointer so that debuggers 1437*7c478bd9Sstevel@tonic-gate * can do a proper stack backtrace from the signal handler. 1438*7c478bd9Sstevel@tonic-gate */ 1439*7c478bd9Sstevel@tonic-gate if (mpcb->mpcb_wbcnt == 0) { 1440*7c478bd9Sstevel@tonic-gate watched2 = watch_disable_addr(tos, sizeof (struct rwindow32), 1441*7c478bd9Sstevel@tonic-gate S_READ); 1442*7c478bd9Sstevel@tonic-gate ucopy(tos, &fp->frwin, sizeof (struct rwindow32)); 1443*7c478bd9Sstevel@tonic-gate } 1444*7c478bd9Sstevel@tonic-gate 1445*7c478bd9Sstevel@tonic-gate lwp->lwp_oldcontext = (uintptr_t)&fp->uc; 1446*7c478bd9Sstevel@tonic-gate 1447*7c478bd9Sstevel@tonic-gate if (newstack != 0) { 1448*7c478bd9Sstevel@tonic-gate lwp->lwp_sigaltstack.ss_flags |= SS_ONSTACK; 1449*7c478bd9Sstevel@tonic-gate if (lwp->lwp_ustack) { 1450*7c478bd9Sstevel@tonic-gate stack32_t stk32; 1451*7c478bd9Sstevel@tonic-gate 1452*7c478bd9Sstevel@tonic-gate stk32.ss_sp = (caddr32_t)lwp->lwp_sigaltstack.ss_sp; 1453*7c478bd9Sstevel@tonic-gate stk32.ss_size = (size32_t)lwp->lwp_sigaltstack.ss_size; 1454*7c478bd9Sstevel@tonic-gate stk32.ss_flags = (int32_t)lwp->lwp_sigaltstack.ss_flags; 1455*7c478bd9Sstevel@tonic-gate 1456*7c478bd9Sstevel@tonic-gate copyout_noerr(&stk32, (stack32_t *)lwp->lwp_ustack, 1457*7c478bd9Sstevel@tonic-gate sizeof (stack32_t)); 1458*7c478bd9Sstevel@tonic-gate } 1459*7c478bd9Sstevel@tonic-gate } 1460*7c478bd9Sstevel@tonic-gate 1461*7c478bd9Sstevel@tonic-gate no_fault(); 1462*7c478bd9Sstevel@tonic-gate mpcb->mpcb_wbcnt = 0; /* let user go on */ 1463*7c478bd9Sstevel@tonic-gate 1464*7c478bd9Sstevel@tonic-gate if (watched2) 1465*7c478bd9Sstevel@tonic-gate watch_enable_addr(tos, sizeof (struct rwindow32), S_READ); 1466*7c478bd9Sstevel@tonic-gate if (watched) 1467*7c478bd9Sstevel@tonic-gate watch_enable_addr((caddr_t)fp, SA32(minstacksz), S_WRITE); 1468*7c478bd9Sstevel@tonic-gate 1469*7c478bd9Sstevel@tonic-gate /* 1470*7c478bd9Sstevel@tonic-gate * Set up user registers for execution of signal handler. 1471*7c478bd9Sstevel@tonic-gate */ 1472*7c478bd9Sstevel@tonic-gate rp->r_sp = (uintptr_t)fp; 1473*7c478bd9Sstevel@tonic-gate rp->r_pc = (uintptr_t)hdlr; 1474*7c478bd9Sstevel@tonic-gate rp->r_npc = (uintptr_t)hdlr + 4; 1475*7c478bd9Sstevel@tonic-gate /* make sure %asi is ASI_PNF */ 1476*7c478bd9Sstevel@tonic-gate rp->r_tstate &= ~((uint64_t)TSTATE_ASI_MASK << TSTATE_ASI_SHIFT); 1477*7c478bd9Sstevel@tonic-gate rp->r_tstate |= ((uint64_t)ASI_PNF << TSTATE_ASI_SHIFT); 1478*7c478bd9Sstevel@tonic-gate rp->r_o0 = sig; 1479*7c478bd9Sstevel@tonic-gate rp->r_o1 = (uintptr_t)sip_addr; 1480*7c478bd9Sstevel@tonic-gate rp->r_o2 = (uintptr_t)&fp->uc; 1481*7c478bd9Sstevel@tonic-gate /* 1482*7c478bd9Sstevel@tonic-gate * Don't set lwp_eosys here. sendsig() is called via psig() after 1483*7c478bd9Sstevel@tonic-gate * lwp_eosys is handled, so setting it here would affect the next 1484*7c478bd9Sstevel@tonic-gate * system call. 1485*7c478bd9Sstevel@tonic-gate */ 1486*7c478bd9Sstevel@tonic-gate return (1); 1487*7c478bd9Sstevel@tonic-gate 1488*7c478bd9Sstevel@tonic-gate badstack: 1489*7c478bd9Sstevel@tonic-gate no_fault(); 1490*7c478bd9Sstevel@tonic-gate if (watched2) 1491*7c478bd9Sstevel@tonic-gate watch_enable_addr(tos, sizeof (struct rwindow32), S_READ); 1492*7c478bd9Sstevel@tonic-gate if (watched) 1493*7c478bd9Sstevel@tonic-gate watch_enable_addr((caddr_t)fp, SA32(minstacksz), S_WRITE); 1494*7c478bd9Sstevel@tonic-gate if (tuc) 1495*7c478bd9Sstevel@tonic-gate kmem_free(tuc, sizeof (*tuc)); 1496*7c478bd9Sstevel@tonic-gate if (xregs) 1497*7c478bd9Sstevel@tonic-gate kmem_free(xregs, xregs_size); 1498*7c478bd9Sstevel@tonic-gate if (gwp) 1499*7c478bd9Sstevel@tonic-gate kmem_free(gwp, gwin_size); 1500*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 1501*7c478bd9Sstevel@tonic-gate printf("sendsig32: bad signal stack cmd=%s, pid=%d, sig=%d\n", 1502*7c478bd9Sstevel@tonic-gate PTOU(p)->u_comm, p->p_pid, sig); 1503*7c478bd9Sstevel@tonic-gate printf("on fault, sigsp = 0x%p, action = 0x%p, upc = 0x%lx\n", 1504*7c478bd9Sstevel@tonic-gate (void *)fp, (void *)hdlr, rp->r_pc); 1505*7c478bd9Sstevel@tonic-gate #endif 1506*7c478bd9Sstevel@tonic-gate return (0); 1507*7c478bd9Sstevel@tonic-gate } 1508*7c478bd9Sstevel@tonic-gate 1509*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 1510*7c478bd9Sstevel@tonic-gate 1511*7c478bd9Sstevel@tonic-gate 1512*7c478bd9Sstevel@tonic-gate /* 1513*7c478bd9Sstevel@tonic-gate * load user registers into lwp. 1514*7c478bd9Sstevel@tonic-gate * thrptr ignored for sparc. 1515*7c478bd9Sstevel@tonic-gate */ 1516*7c478bd9Sstevel@tonic-gate /* ARGSUSED2 */ 1517*7c478bd9Sstevel@tonic-gate void 1518*7c478bd9Sstevel@tonic-gate lwp_load(klwp_t *lwp, gregset_t grp, uintptr_t thrptr) 1519*7c478bd9Sstevel@tonic-gate { 1520*7c478bd9Sstevel@tonic-gate setgregs(lwp, grp); 1521*7c478bd9Sstevel@tonic-gate if (lwptoproc(lwp)->p_model == DATAMODEL_ILP32) 1522*7c478bd9Sstevel@tonic-gate lwptoregs(lwp)->r_tstate = TSTATE_USER32; 1523*7c478bd9Sstevel@tonic-gate else 1524*7c478bd9Sstevel@tonic-gate lwptoregs(lwp)->r_tstate = TSTATE_USER64; 1525*7c478bd9Sstevel@tonic-gate 1526*7c478bd9Sstevel@tonic-gate if (!fpu_exists) 1527*7c478bd9Sstevel@tonic-gate lwptoregs(lwp)->r_tstate &= ~TSTATE_PEF; 1528*7c478bd9Sstevel@tonic-gate lwp->lwp_eosys = JUSTRETURN; 1529*7c478bd9Sstevel@tonic-gate lwptot(lwp)->t_post_sys = 1; 1530*7c478bd9Sstevel@tonic-gate } 1531*7c478bd9Sstevel@tonic-gate 1532*7c478bd9Sstevel@tonic-gate /* 1533*7c478bd9Sstevel@tonic-gate * set syscall()'s return values for a lwp. 1534*7c478bd9Sstevel@tonic-gate */ 1535*7c478bd9Sstevel@tonic-gate void 1536*7c478bd9Sstevel@tonic-gate lwp_setrval(klwp_t *lwp, int v1, int v2) 1537*7c478bd9Sstevel@tonic-gate { 1538*7c478bd9Sstevel@tonic-gate struct regs *rp = lwptoregs(lwp); 1539*7c478bd9Sstevel@tonic-gate 1540*7c478bd9Sstevel@tonic-gate rp->r_tstate &= ~TSTATE_IC; 1541*7c478bd9Sstevel@tonic-gate rp->r_o0 = v1; 1542*7c478bd9Sstevel@tonic-gate rp->r_o1 = v2; 1543*7c478bd9Sstevel@tonic-gate } 1544*7c478bd9Sstevel@tonic-gate 1545*7c478bd9Sstevel@tonic-gate /* 1546*7c478bd9Sstevel@tonic-gate * set stack pointer for a lwp 1547*7c478bd9Sstevel@tonic-gate */ 1548*7c478bd9Sstevel@tonic-gate void 1549*7c478bd9Sstevel@tonic-gate lwp_setsp(klwp_t *lwp, caddr_t sp) 1550*7c478bd9Sstevel@tonic-gate { 1551*7c478bd9Sstevel@tonic-gate struct regs *rp = lwptoregs(lwp); 1552*7c478bd9Sstevel@tonic-gate rp->r_sp = (uintptr_t)sp; 1553*7c478bd9Sstevel@tonic-gate } 1554*7c478bd9Sstevel@tonic-gate 1555*7c478bd9Sstevel@tonic-gate /* 1556*7c478bd9Sstevel@tonic-gate * Take any PCB specific actions that are required or flagged in the PCB. 1557*7c478bd9Sstevel@tonic-gate */ 1558*7c478bd9Sstevel@tonic-gate extern void trap_async_hwerr(void); 1559*7c478bd9Sstevel@tonic-gate #pragma weak trap_async_hwerr 1560*7c478bd9Sstevel@tonic-gate 1561*7c478bd9Sstevel@tonic-gate void 1562*7c478bd9Sstevel@tonic-gate lwp_pcb_exit(void) 1563*7c478bd9Sstevel@tonic-gate { 1564*7c478bd9Sstevel@tonic-gate klwp_t *lwp = ttolwp(curthread); 1565*7c478bd9Sstevel@tonic-gate 1566*7c478bd9Sstevel@tonic-gate if (lwp->lwp_pcb.pcb_flags & ASYNC_HWERR) { 1567*7c478bd9Sstevel@tonic-gate trap_async_hwerr(); 1568*7c478bd9Sstevel@tonic-gate } 1569*7c478bd9Sstevel@tonic-gate } 1570*7c478bd9Sstevel@tonic-gate 1571*7c478bd9Sstevel@tonic-gate /* 1572*7c478bd9Sstevel@tonic-gate * Invalidate the saved user register windows in the pcb struct 1573*7c478bd9Sstevel@tonic-gate * for the current thread. They will no longer be preserved. 1574*7c478bd9Sstevel@tonic-gate */ 1575*7c478bd9Sstevel@tonic-gate void 1576*7c478bd9Sstevel@tonic-gate lwp_clear_uwin(void) 1577*7c478bd9Sstevel@tonic-gate { 1578*7c478bd9Sstevel@tonic-gate struct machpcb *m = lwptompcb(ttolwp(curthread)); 1579*7c478bd9Sstevel@tonic-gate 1580*7c478bd9Sstevel@tonic-gate /* 1581*7c478bd9Sstevel@tonic-gate * This has the effect of invalidating all (any) of the 1582*7c478bd9Sstevel@tonic-gate * user level windows that are currently sitting in the 1583*7c478bd9Sstevel@tonic-gate * kernel buffer. 1584*7c478bd9Sstevel@tonic-gate */ 1585*7c478bd9Sstevel@tonic-gate m->mpcb_wbcnt = 0; 1586*7c478bd9Sstevel@tonic-gate } 1587*7c478bd9Sstevel@tonic-gate 1588*7c478bd9Sstevel@tonic-gate static uint_t 1589*7c478bd9Sstevel@tonic-gate mkpsr(uint64_t tstate, uint_t fprs) 1590*7c478bd9Sstevel@tonic-gate { 1591*7c478bd9Sstevel@tonic-gate uint_t psr, icc; 1592*7c478bd9Sstevel@tonic-gate 1593*7c478bd9Sstevel@tonic-gate psr = tstate & TSTATE_CWP_MASK; 1594*7c478bd9Sstevel@tonic-gate if (tstate & TSTATE_PRIV) 1595*7c478bd9Sstevel@tonic-gate psr |= PSR_PS; 1596*7c478bd9Sstevel@tonic-gate if (fprs & FPRS_FEF) 1597*7c478bd9Sstevel@tonic-gate psr |= PSR_EF; 1598*7c478bd9Sstevel@tonic-gate icc = (uint_t)(tstate >> PSR_TSTATE_CC_SHIFT) & PSR_ICC; 1599*7c478bd9Sstevel@tonic-gate psr |= icc; 1600*7c478bd9Sstevel@tonic-gate psr |= V9_PSR_IMPLVER; 1601*7c478bd9Sstevel@tonic-gate return (psr); 1602*7c478bd9Sstevel@tonic-gate } 1603*7c478bd9Sstevel@tonic-gate 1604*7c478bd9Sstevel@tonic-gate void 1605*7c478bd9Sstevel@tonic-gate sync_icache(caddr_t va, uint_t len) 1606*7c478bd9Sstevel@tonic-gate { 1607*7c478bd9Sstevel@tonic-gate caddr_t end; 1608*7c478bd9Sstevel@tonic-gate 1609*7c478bd9Sstevel@tonic-gate end = va + len; 1610*7c478bd9Sstevel@tonic-gate va = (caddr_t)((uintptr_t)va & -8l); /* sparc needs 8-byte align */ 1611*7c478bd9Sstevel@tonic-gate while (va < end) { 1612*7c478bd9Sstevel@tonic-gate doflush(va); 1613*7c478bd9Sstevel@tonic-gate va += 8; 1614*7c478bd9Sstevel@tonic-gate } 1615*7c478bd9Sstevel@tonic-gate } 1616*7c478bd9Sstevel@tonic-gate 1617*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 1618*7c478bd9Sstevel@tonic-gate 1619*7c478bd9Sstevel@tonic-gate /* 1620*7c478bd9Sstevel@tonic-gate * Copy the floating point queue if and only if there is a queue and a place 1621*7c478bd9Sstevel@tonic-gate * to copy it to. Let xregs take care of the other fp regs, for v8plus. 1622*7c478bd9Sstevel@tonic-gate * The issue is that while we are handling the fq32 in sendsig, we 1623*7c478bd9Sstevel@tonic-gate * still need a 64-bit pointer to it, and the caddr32_t in fpregset32_t 1624*7c478bd9Sstevel@tonic-gate * will not suffice, so we have the third parameter to this function. 1625*7c478bd9Sstevel@tonic-gate */ 1626*7c478bd9Sstevel@tonic-gate void 1627*7c478bd9Sstevel@tonic-gate fpuregset_nto32(const fpregset_t *src, fpregset32_t *dest, struct fq32 *dfq) 1628*7c478bd9Sstevel@tonic-gate { 1629*7c478bd9Sstevel@tonic-gate int i; 1630*7c478bd9Sstevel@tonic-gate 1631*7c478bd9Sstevel@tonic-gate bzero(dest, sizeof (*dest)); 1632*7c478bd9Sstevel@tonic-gate for (i = 0; i < 32; i++) 1633*7c478bd9Sstevel@tonic-gate dest->fpu_fr.fpu_regs[i] = src->fpu_fr.fpu_regs[i]; 1634*7c478bd9Sstevel@tonic-gate dest->fpu_q = NULL; 1635*7c478bd9Sstevel@tonic-gate dest->fpu_fsr = (uint32_t)src->fpu_fsr; 1636*7c478bd9Sstevel@tonic-gate dest->fpu_qcnt = src->fpu_qcnt; 1637*7c478bd9Sstevel@tonic-gate dest->fpu_q_entrysize = sizeof (struct fpq32); 1638*7c478bd9Sstevel@tonic-gate dest->fpu_en = src->fpu_en; 1639*7c478bd9Sstevel@tonic-gate 1640*7c478bd9Sstevel@tonic-gate if ((src->fpu_qcnt) && (dfq != NULL)) { 1641*7c478bd9Sstevel@tonic-gate struct fq *sfq = src->fpu_q; 1642*7c478bd9Sstevel@tonic-gate for (i = 0; i < src->fpu_qcnt; i++, dfq++, sfq++) { 1643*7c478bd9Sstevel@tonic-gate dfq->FQu.fpq.fpq_addr = 1644*7c478bd9Sstevel@tonic-gate (caddr32_t)sfq->FQu.fpq.fpq_addr; 1645*7c478bd9Sstevel@tonic-gate dfq->FQu.fpq.fpq_instr = sfq->FQu.fpq.fpq_instr; 1646*7c478bd9Sstevel@tonic-gate } 1647*7c478bd9Sstevel@tonic-gate } 1648*7c478bd9Sstevel@tonic-gate } 1649*7c478bd9Sstevel@tonic-gate 1650*7c478bd9Sstevel@tonic-gate /* 1651*7c478bd9Sstevel@tonic-gate * Copy the floating point queue if and only if there is a queue and a place 1652*7c478bd9Sstevel@tonic-gate * to copy it to. Let xregs take care of the other fp regs, for v8plus. 1653*7c478bd9Sstevel@tonic-gate * The *dfq is required to escape the bzero in both this function and in 1654*7c478bd9Sstevel@tonic-gate * ucontext_32ton. The *sfq is required because once the fq32 is copied 1655*7c478bd9Sstevel@tonic-gate * into the kernel, in setcontext, then we need a 64-bit pointer to it. 1656*7c478bd9Sstevel@tonic-gate */ 1657*7c478bd9Sstevel@tonic-gate static void 1658*7c478bd9Sstevel@tonic-gate fpuregset_32ton(const fpregset32_t *src, fpregset_t *dest, 1659*7c478bd9Sstevel@tonic-gate const struct fq32 *sfq, struct fq *dfq) 1660*7c478bd9Sstevel@tonic-gate { 1661*7c478bd9Sstevel@tonic-gate int i; 1662*7c478bd9Sstevel@tonic-gate 1663*7c478bd9Sstevel@tonic-gate bzero(dest, sizeof (*dest)); 1664*7c478bd9Sstevel@tonic-gate for (i = 0; i < 32; i++) 1665*7c478bd9Sstevel@tonic-gate dest->fpu_fr.fpu_regs[i] = src->fpu_fr.fpu_regs[i]; 1666*7c478bd9Sstevel@tonic-gate dest->fpu_q = dfq; 1667*7c478bd9Sstevel@tonic-gate dest->fpu_fsr = (uint64_t)src->fpu_fsr; 1668*7c478bd9Sstevel@tonic-gate if ((dest->fpu_qcnt = src->fpu_qcnt) > 0) 1669*7c478bd9Sstevel@tonic-gate dest->fpu_q_entrysize = sizeof (struct fpq); 1670*7c478bd9Sstevel@tonic-gate else 1671*7c478bd9Sstevel@tonic-gate dest->fpu_q_entrysize = 0; 1672*7c478bd9Sstevel@tonic-gate dest->fpu_en = src->fpu_en; 1673*7c478bd9Sstevel@tonic-gate 1674*7c478bd9Sstevel@tonic-gate if ((src->fpu_qcnt) && (sfq) && (dfq)) { 1675*7c478bd9Sstevel@tonic-gate for (i = 0; i < src->fpu_qcnt; i++, dfq++, sfq++) { 1676*7c478bd9Sstevel@tonic-gate dfq->FQu.fpq.fpq_addr = 1677*7c478bd9Sstevel@tonic-gate (unsigned int *)sfq->FQu.fpq.fpq_addr; 1678*7c478bd9Sstevel@tonic-gate dfq->FQu.fpq.fpq_instr = sfq->FQu.fpq.fpq_instr; 1679*7c478bd9Sstevel@tonic-gate } 1680*7c478bd9Sstevel@tonic-gate } 1681*7c478bd9Sstevel@tonic-gate } 1682*7c478bd9Sstevel@tonic-gate 1683*7c478bd9Sstevel@tonic-gate void 1684*7c478bd9Sstevel@tonic-gate ucontext_32ton(const ucontext32_t *src, ucontext_t *dest, 1685*7c478bd9Sstevel@tonic-gate const struct fq32 *sfq, struct fq *dfq) 1686*7c478bd9Sstevel@tonic-gate { 1687*7c478bd9Sstevel@tonic-gate int i; 1688*7c478bd9Sstevel@tonic-gate 1689*7c478bd9Sstevel@tonic-gate bzero(dest, sizeof (*dest)); 1690*7c478bd9Sstevel@tonic-gate 1691*7c478bd9Sstevel@tonic-gate dest->uc_flags = src->uc_flags; 1692*7c478bd9Sstevel@tonic-gate dest->uc_link = (ucontext_t *)src->uc_link; 1693*7c478bd9Sstevel@tonic-gate 1694*7c478bd9Sstevel@tonic-gate for (i = 0; i < 4; i++) { 1695*7c478bd9Sstevel@tonic-gate dest->uc_sigmask.__sigbits[i] = src->uc_sigmask.__sigbits[i]; 1696*7c478bd9Sstevel@tonic-gate } 1697*7c478bd9Sstevel@tonic-gate 1698*7c478bd9Sstevel@tonic-gate dest->uc_stack.ss_sp = (void *)src->uc_stack.ss_sp; 1699*7c478bd9Sstevel@tonic-gate dest->uc_stack.ss_size = (size_t)src->uc_stack.ss_size; 1700*7c478bd9Sstevel@tonic-gate dest->uc_stack.ss_flags = src->uc_stack.ss_flags; 1701*7c478bd9Sstevel@tonic-gate 1702*7c478bd9Sstevel@tonic-gate /* REG_CCR is 0, skip over it and handle it after this loop */ 1703*7c478bd9Sstevel@tonic-gate for (i = 1; i < _NGREG32; i++) 1704*7c478bd9Sstevel@tonic-gate dest->uc_mcontext.gregs[i] = 1705*7c478bd9Sstevel@tonic-gate (greg_t)(uint32_t)src->uc_mcontext.gregs[i]; 1706*7c478bd9Sstevel@tonic-gate dest->uc_mcontext.gregs[REG_CCR] = 1707*7c478bd9Sstevel@tonic-gate (src->uc_mcontext.gregs[REG_PSR] & PSR_ICC) >> PSR_ICC_SHIFT; 1708*7c478bd9Sstevel@tonic-gate dest->uc_mcontext.gregs[REG_ASI] = ASI_PNF; 1709*7c478bd9Sstevel@tonic-gate /* 1710*7c478bd9Sstevel@tonic-gate * A valid fpregs is only copied in if (uc.uc_flags & UC_FPU), 1711*7c478bd9Sstevel@tonic-gate * otherwise there is no guarantee that anything in fpregs is valid. 1712*7c478bd9Sstevel@tonic-gate */ 1713*7c478bd9Sstevel@tonic-gate if (src->uc_flags & UC_FPU) { 1714*7c478bd9Sstevel@tonic-gate dest->uc_mcontext.gregs[REG_FPRS] = 1715*7c478bd9Sstevel@tonic-gate ((src->uc_mcontext.fpregs.fpu_en) ? 1716*7c478bd9Sstevel@tonic-gate (FPRS_DU|FPRS_DL|FPRS_FEF) : 0); 1717*7c478bd9Sstevel@tonic-gate } else { 1718*7c478bd9Sstevel@tonic-gate dest->uc_mcontext.gregs[REG_FPRS] = 0; 1719*7c478bd9Sstevel@tonic-gate } 1720*7c478bd9Sstevel@tonic-gate dest->uc_mcontext.gwins = (gwindows_t *)src->uc_mcontext.gwins; 1721*7c478bd9Sstevel@tonic-gate if (src->uc_flags & UC_FPU) { 1722*7c478bd9Sstevel@tonic-gate fpuregset_32ton(&src->uc_mcontext.fpregs, 1723*7c478bd9Sstevel@tonic-gate &dest->uc_mcontext.fpregs, sfq, dfq); 1724*7c478bd9Sstevel@tonic-gate } 1725*7c478bd9Sstevel@tonic-gate } 1726*7c478bd9Sstevel@tonic-gate 1727*7c478bd9Sstevel@tonic-gate void 1728*7c478bd9Sstevel@tonic-gate rwindow_nto32(struct rwindow *src, struct rwindow32 *dest) 1729*7c478bd9Sstevel@tonic-gate { 1730*7c478bd9Sstevel@tonic-gate greg_t *s = (greg_t *)src; 1731*7c478bd9Sstevel@tonic-gate greg32_t *d = (greg32_t *)dest; 1732*7c478bd9Sstevel@tonic-gate int i; 1733*7c478bd9Sstevel@tonic-gate 1734*7c478bd9Sstevel@tonic-gate for (i = 0; i < 16; i++) 1735*7c478bd9Sstevel@tonic-gate *d++ = (greg32_t)*s++; 1736*7c478bd9Sstevel@tonic-gate } 1737*7c478bd9Sstevel@tonic-gate 1738*7c478bd9Sstevel@tonic-gate void 1739*7c478bd9Sstevel@tonic-gate rwindow_32ton(struct rwindow32 *src, struct rwindow *dest) 1740*7c478bd9Sstevel@tonic-gate { 1741*7c478bd9Sstevel@tonic-gate greg32_t *s = (greg32_t *)src; 1742*7c478bd9Sstevel@tonic-gate greg_t *d = (greg_t *)dest; 1743*7c478bd9Sstevel@tonic-gate int i; 1744*7c478bd9Sstevel@tonic-gate 1745*7c478bd9Sstevel@tonic-gate for (i = 0; i < 16; i++) 1746*7c478bd9Sstevel@tonic-gate *d++ = (uint32_t)*s++; 1747*7c478bd9Sstevel@tonic-gate } 1748*7c478bd9Sstevel@tonic-gate 1749*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 1750*7c478bd9Sstevel@tonic-gate 1751*7c478bd9Sstevel@tonic-gate /* 1752*7c478bd9Sstevel@tonic-gate * The panic code invokes panic_saveregs() to record the contents of a 1753*7c478bd9Sstevel@tonic-gate * regs structure into the specified panic_data structure for debuggers. 1754*7c478bd9Sstevel@tonic-gate */ 1755*7c478bd9Sstevel@tonic-gate void 1756*7c478bd9Sstevel@tonic-gate panic_saveregs(panic_data_t *pdp, struct regs *rp) 1757*7c478bd9Sstevel@tonic-gate { 1758*7c478bd9Sstevel@tonic-gate panic_nv_t *pnv = PANICNVGET(pdp); 1759*7c478bd9Sstevel@tonic-gate 1760*7c478bd9Sstevel@tonic-gate PANICNVADD(pnv, "tstate", rp->r_tstate); 1761*7c478bd9Sstevel@tonic-gate PANICNVADD(pnv, "g1", rp->r_g1); 1762*7c478bd9Sstevel@tonic-gate PANICNVADD(pnv, "g2", rp->r_g2); 1763*7c478bd9Sstevel@tonic-gate PANICNVADD(pnv, "g3", rp->r_g3); 1764*7c478bd9Sstevel@tonic-gate PANICNVADD(pnv, "g4", rp->r_g4); 1765*7c478bd9Sstevel@tonic-gate PANICNVADD(pnv, "g5", rp->r_g5); 1766*7c478bd9Sstevel@tonic-gate PANICNVADD(pnv, "g6", rp->r_g6); 1767*7c478bd9Sstevel@tonic-gate PANICNVADD(pnv, "g7", rp->r_g7); 1768*7c478bd9Sstevel@tonic-gate PANICNVADD(pnv, "o0", rp->r_o0); 1769*7c478bd9Sstevel@tonic-gate PANICNVADD(pnv, "o1", rp->r_o1); 1770*7c478bd9Sstevel@tonic-gate PANICNVADD(pnv, "o2", rp->r_o2); 1771*7c478bd9Sstevel@tonic-gate PANICNVADD(pnv, "o3", rp->r_o3); 1772*7c478bd9Sstevel@tonic-gate PANICNVADD(pnv, "o4", rp->r_o4); 1773*7c478bd9Sstevel@tonic-gate PANICNVADD(pnv, "o5", rp->r_o5); 1774*7c478bd9Sstevel@tonic-gate PANICNVADD(pnv, "o6", rp->r_o6); 1775*7c478bd9Sstevel@tonic-gate PANICNVADD(pnv, "o7", rp->r_o7); 1776*7c478bd9Sstevel@tonic-gate PANICNVADD(pnv, "pc", (ulong_t)rp->r_pc); 1777*7c478bd9Sstevel@tonic-gate PANICNVADD(pnv, "npc", (ulong_t)rp->r_npc); 1778*7c478bd9Sstevel@tonic-gate PANICNVADD(pnv, "y", (uint32_t)rp->r_y); 1779*7c478bd9Sstevel@tonic-gate 1780*7c478bd9Sstevel@tonic-gate PANICNVSET(pdp, pnv); 1781*7c478bd9Sstevel@tonic-gate } 1782