1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include "lint.h" 30*0Sstevel@tonic-gate #include "thr_uberdata.h" 31*0Sstevel@tonic-gate #include <procfs.h> 32*0Sstevel@tonic-gate #include <setjmp.h> 33*0Sstevel@tonic-gate #include <sys/fsr.h> 34*0Sstevel@tonic-gate #include "sigjmp_struct.h" 35*0Sstevel@tonic-gate 36*0Sstevel@tonic-gate extern int getlwpstatus(thread_t, lwpstatus_t *); 37*0Sstevel@tonic-gate extern int putlwpregs(thread_t, prgregset_t); 38*0Sstevel@tonic-gate 39*0Sstevel@tonic-gate int 40*0Sstevel@tonic-gate setup_context(ucontext_t *ucp, void *(*func)(ulwp_t *), 41*0Sstevel@tonic-gate ulwp_t *ulwp, caddr_t stk, size_t stksize) 42*0Sstevel@tonic-gate { 43*0Sstevel@tonic-gate /* 44*0Sstevel@tonic-gate * Top-of-stack must be rounded down to STACK_ALIGN and 45*0Sstevel@tonic-gate * there must be a minimum frame for the register window. 46*0Sstevel@tonic-gate */ 47*0Sstevel@tonic-gate uintptr_t stack = (((uintptr_t)stk + stksize) & ~(STACK_ALIGN - 1)) - 48*0Sstevel@tonic-gate SA(MINFRAME); 49*0Sstevel@tonic-gate 50*0Sstevel@tonic-gate /* clear the context and the top stack frame */ 51*0Sstevel@tonic-gate (void) _memset(ucp, 0, sizeof (*ucp)); 52*0Sstevel@tonic-gate (void) _memset((void *)stack, 0, SA(MINFRAME)); 53*0Sstevel@tonic-gate 54*0Sstevel@tonic-gate /* fill in registers of interest */ 55*0Sstevel@tonic-gate ucp->uc_flags |= UC_CPU; 56*0Sstevel@tonic-gate ucp->uc_mcontext.gregs[REG_PC] = (greg_t)func; 57*0Sstevel@tonic-gate ucp->uc_mcontext.gregs[REG_nPC] = (greg_t)func + 4; 58*0Sstevel@tonic-gate ucp->uc_mcontext.gregs[REG_O0] = (greg_t)ulwp; 59*0Sstevel@tonic-gate ucp->uc_mcontext.gregs[REG_SP] = (greg_t)(stack - STACK_BIAS); 60*0Sstevel@tonic-gate ucp->uc_mcontext.gregs[REG_O7] = (greg_t)_lwp_start; 61*0Sstevel@tonic-gate ucp->uc_mcontext.gregs[REG_G7] = (greg_t)ulwp; 62*0Sstevel@tonic-gate 63*0Sstevel@tonic-gate return (0); 64*0Sstevel@tonic-gate } 65*0Sstevel@tonic-gate 66*0Sstevel@tonic-gate /* 67*0Sstevel@tonic-gate * Machine-dependent startup code for a newly-created thread. 68*0Sstevel@tonic-gate */ 69*0Sstevel@tonic-gate void * 70*0Sstevel@tonic-gate _thr_setup(ulwp_t *self) 71*0Sstevel@tonic-gate { 72*0Sstevel@tonic-gate extern void _setfsr(greg_t *); 73*0Sstevel@tonic-gate 74*0Sstevel@tonic-gate if (self->ul_fpuenv.fpu_en) 75*0Sstevel@tonic-gate _setfsr(&self->ul_fpuenv.fsr); 76*0Sstevel@tonic-gate 77*0Sstevel@tonic-gate self->ul_ustack.ss_sp = (void *)(self->ul_stktop - self->ul_stksiz); 78*0Sstevel@tonic-gate self->ul_ustack.ss_size = self->ul_stksiz; 79*0Sstevel@tonic-gate self->ul_ustack.ss_flags = 0; 80*0Sstevel@tonic-gate (void) _private_setustack(&self->ul_ustack); 81*0Sstevel@tonic-gate tls_setup(); 82*0Sstevel@tonic-gate 83*0Sstevel@tonic-gate /* signals have been deferred until now */ 84*0Sstevel@tonic-gate sigon(self); 85*0Sstevel@tonic-gate 86*0Sstevel@tonic-gate return (self->ul_startpc(self->ul_startarg)); 87*0Sstevel@tonic-gate } 88*0Sstevel@tonic-gate 89*0Sstevel@tonic-gate void 90*0Sstevel@tonic-gate _fpinherit(ulwp_t *ulwp) 91*0Sstevel@tonic-gate { 92*0Sstevel@tonic-gate extern void _getfsr(greg_t *); 93*0Sstevel@tonic-gate int fpu_enabled; 94*0Sstevel@tonic-gate 95*0Sstevel@tonic-gate #ifdef __sparcv9 96*0Sstevel@tonic-gate extern greg_t _getfprs(); 97*0Sstevel@tonic-gate fpu_enabled = _getfprs() & FPRS_FEF; 98*0Sstevel@tonic-gate #else 99*0Sstevel@tonic-gate extern psw_t _getpsr(); 100*0Sstevel@tonic-gate fpu_enabled = _getpsr() & PSR_EF; 101*0Sstevel@tonic-gate #endif /* __sparcv9 */ 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gate if (fpu_enabled) { 104*0Sstevel@tonic-gate _getfsr(&ulwp->ul_fpuenv.fsr); 105*0Sstevel@tonic-gate ulwp->ul_fpuenv.fpu_en = 1; 106*0Sstevel@tonic-gate } else { 107*0Sstevel@tonic-gate ulwp->ul_fpuenv.fpu_en = 0; 108*0Sstevel@tonic-gate } 109*0Sstevel@tonic-gate } 110*0Sstevel@tonic-gate 111*0Sstevel@tonic-gate void 112*0Sstevel@tonic-gate getgregs(ulwp_t *ulwp, gregset_t rs) 113*0Sstevel@tonic-gate { 114*0Sstevel@tonic-gate lwpstatus_t status; 115*0Sstevel@tonic-gate 116*0Sstevel@tonic-gate if (getlwpstatus(ulwp->ul_lwpid, &status) == 0) { 117*0Sstevel@tonic-gate rs[REG_PC] = status.pr_reg[R_PC]; 118*0Sstevel@tonic-gate rs[REG_O6] = status.pr_reg[R_O6]; 119*0Sstevel@tonic-gate rs[REG_O7] = status.pr_reg[R_O7]; 120*0Sstevel@tonic-gate rs[REG_G1] = status.pr_reg[R_G1]; 121*0Sstevel@tonic-gate rs[REG_G2] = status.pr_reg[R_G2]; 122*0Sstevel@tonic-gate rs[REG_G3] = status.pr_reg[R_G3]; 123*0Sstevel@tonic-gate rs[REG_G4] = status.pr_reg[R_G4]; 124*0Sstevel@tonic-gate } else { 125*0Sstevel@tonic-gate rs[REG_PC] = 0; 126*0Sstevel@tonic-gate rs[REG_O6] = 0; 127*0Sstevel@tonic-gate rs[REG_O7] = 0; 128*0Sstevel@tonic-gate rs[REG_G1] = 0; 129*0Sstevel@tonic-gate rs[REG_G2] = 0; 130*0Sstevel@tonic-gate rs[REG_G3] = 0; 131*0Sstevel@tonic-gate rs[REG_G4] = 0; 132*0Sstevel@tonic-gate } 133*0Sstevel@tonic-gate } 134*0Sstevel@tonic-gate 135*0Sstevel@tonic-gate void 136*0Sstevel@tonic-gate setgregs(ulwp_t *ulwp, gregset_t rs) 137*0Sstevel@tonic-gate { 138*0Sstevel@tonic-gate lwpstatus_t status; 139*0Sstevel@tonic-gate 140*0Sstevel@tonic-gate if (getlwpstatus(ulwp->ul_lwpid, &status) == 0) { 141*0Sstevel@tonic-gate status.pr_reg[R_PC] = rs[REG_PC]; 142*0Sstevel@tonic-gate status.pr_reg[R_O6] = rs[REG_O6]; 143*0Sstevel@tonic-gate status.pr_reg[R_O7] = rs[REG_O7]; 144*0Sstevel@tonic-gate status.pr_reg[R_G1] = rs[REG_G1]; 145*0Sstevel@tonic-gate status.pr_reg[R_G2] = rs[REG_G2]; 146*0Sstevel@tonic-gate status.pr_reg[R_G3] = rs[REG_G3]; 147*0Sstevel@tonic-gate status.pr_reg[R_G4] = rs[REG_G4]; 148*0Sstevel@tonic-gate (void) putlwpregs(ulwp->ul_lwpid, status.pr_reg); 149*0Sstevel@tonic-gate } 150*0Sstevel@tonic-gate } 151*0Sstevel@tonic-gate 152*0Sstevel@tonic-gate int 153*0Sstevel@tonic-gate __csigsetjmp(sigjmp_buf env, int savemask) 154*0Sstevel@tonic-gate { 155*0Sstevel@tonic-gate sigjmp_struct_t *bp = (sigjmp_struct_t *)env; 156*0Sstevel@tonic-gate ulwp_t *self = curthread; 157*0Sstevel@tonic-gate 158*0Sstevel@tonic-gate /* 159*0Sstevel@tonic-gate * bp->sjs_sp, bp->sjs_pc, bp->sjs_fp and bp->sjs_i7 are already set. 160*0Sstevel@tonic-gate */ 161*0Sstevel@tonic-gate bp->sjs_flags = JB_FRAMEPTR; 162*0Sstevel@tonic-gate bp->sjs_uclink = self->ul_siglink; 163*0Sstevel@tonic-gate if (self->ul_ustack.ss_flags & SS_ONSTACK) 164*0Sstevel@tonic-gate bp->sjs_stack = self->ul_ustack; 165*0Sstevel@tonic-gate else { 166*0Sstevel@tonic-gate bp->sjs_stack.ss_sp = 167*0Sstevel@tonic-gate (void *)(self->ul_stktop - self->ul_stksiz); 168*0Sstevel@tonic-gate bp->sjs_stack.ss_size = self->ul_stksiz; 169*0Sstevel@tonic-gate bp->sjs_stack.ss_flags = 0; 170*0Sstevel@tonic-gate } 171*0Sstevel@tonic-gate if (savemask) { 172*0Sstevel@tonic-gate bp->sjs_flags |= JB_SAVEMASK; 173*0Sstevel@tonic-gate enter_critical(self); 174*0Sstevel@tonic-gate bp->sjs_sigmask = self->ul_sigmask; 175*0Sstevel@tonic-gate exit_critical(self); 176*0Sstevel@tonic-gate } 177*0Sstevel@tonic-gate 178*0Sstevel@tonic-gate return (0); 179*0Sstevel@tonic-gate } 180