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 <sys/types.h> 30*0Sstevel@tonic-gate #include <sys/errno.h> 31*0Sstevel@tonic-gate #include <sys/systm.h> 32*0Sstevel@tonic-gate #include <sys/atomic.h> 33*0Sstevel@tonic-gate #include <sys/kmem.h> 34*0Sstevel@tonic-gate #include <sys/machpcb.h> 35*0Sstevel@tonic-gate #include <sys/utrap.h> 36*0Sstevel@tonic-gate #include <sys/model.h> 37*0Sstevel@tonic-gate #include <sys/cmn_err.h> 38*0Sstevel@tonic-gate 39*0Sstevel@tonic-gate int 40*0Sstevel@tonic-gate install_utrap(utrap_entry_t type, utrap_handler_t new_handler, 41*0Sstevel@tonic-gate utrap_handler_t *old_handlerp) 42*0Sstevel@tonic-gate { 43*0Sstevel@tonic-gate struct proc *p = curthread->t_procp; 44*0Sstevel@tonic-gate utrap_handler_t *ov, *nv, *pv, *sv, *tmp; 45*0Sstevel@tonic-gate int idx; 46*0Sstevel@tonic-gate 47*0Sstevel@tonic-gate /* 48*0Sstevel@tonic-gate * Check trap number. 49*0Sstevel@tonic-gate */ 50*0Sstevel@tonic-gate switch (type) { 51*0Sstevel@tonic-gate case UTRAP_V8P_FP_DISABLED: 52*0Sstevel@tonic-gate #ifdef SF_ERRATA_30 /* call causes fp-disabled */ 53*0Sstevel@tonic-gate { 54*0Sstevel@tonic-gate extern int spitfire_call_bug; 55*0Sstevel@tonic-gate 56*0Sstevel@tonic-gate if (spitfire_call_bug) { 57*0Sstevel@tonic-gate cmn_err(CE_WARN, "UTRAP_V8P_FP_DISABLED " 58*0Sstevel@tonic-gate "not supported for cpu version < 2.2"); 59*0Sstevel@tonic-gate return ((int)set_errno(ENOSYS)); 60*0Sstevel@tonic-gate } 61*0Sstevel@tonic-gate } 62*0Sstevel@tonic-gate #endif /* SF_ERRATA_30 */ 63*0Sstevel@tonic-gate idx = UTRAP_V8P_FP_DISABLED; 64*0Sstevel@tonic-gate break; 65*0Sstevel@tonic-gate case UTRAP_V8P_MEM_ADDRESS_NOT_ALIGNED: 66*0Sstevel@tonic-gate idx = UTRAP_V8P_MEM_ADDRESS_NOT_ALIGNED; 67*0Sstevel@tonic-gate break; 68*0Sstevel@tonic-gate default: 69*0Sstevel@tonic-gate return ((int)set_errno(EINVAL)); 70*0Sstevel@tonic-gate } 71*0Sstevel@tonic-gate if (get_udatamodel() == DATAMODEL_LP64) { 72*0Sstevel@tonic-gate cmn_err(CE_WARN, "install_utrap private interface " 73*0Sstevel@tonic-gate "not supported for LP64 user programs"); 74*0Sstevel@tonic-gate return ((int)set_errno(EINVAL)); 75*0Sstevel@tonic-gate } 76*0Sstevel@tonic-gate 77*0Sstevel@tonic-gate /* 78*0Sstevel@tonic-gate * Be sure handler address is word aligned. 79*0Sstevel@tonic-gate */ 80*0Sstevel@tonic-gate nv = (utrap_handler_t *)(caddr32_t)new_handler; 81*0Sstevel@tonic-gate if (nv != UTRAP_UTH_NOCHANGE) { 82*0Sstevel@tonic-gate if (((uintptr_t)nv) & 0x3) 83*0Sstevel@tonic-gate return ((int)set_errno(EINVAL)); 84*0Sstevel@tonic-gate } 85*0Sstevel@tonic-gate /* 86*0Sstevel@tonic-gate * Allocate proc space for saving the addresses to these user 87*0Sstevel@tonic-gate * trap handlers, which must later be freed. Use casptr to 88*0Sstevel@tonic-gate * do this atomically. 89*0Sstevel@tonic-gate */ 90*0Sstevel@tonic-gate if (p->p_utraps == NULL) { 91*0Sstevel@tonic-gate pv = sv = kmem_zalloc((UT_PRECISE_MAXTRAPS+1) * 92*0Sstevel@tonic-gate sizeof (utrap_handler_t *), KM_SLEEP); 93*0Sstevel@tonic-gate tmp = casptr(&p->p_utraps, NULL, sv); 94*0Sstevel@tonic-gate if (tmp != NULL) { 95*0Sstevel@tonic-gate kmem_free(pv, (UT_PRECISE_MAXTRAPS+1) * 96*0Sstevel@tonic-gate sizeof (utrap_handler_t *)); 97*0Sstevel@tonic-gate } 98*0Sstevel@tonic-gate } 99*0Sstevel@tonic-gate ASSERT(p->p_utraps != NULL); 100*0Sstevel@tonic-gate 101*0Sstevel@tonic-gate /* 102*0Sstevel@tonic-gate * Use casptr to atomically install the handler. 103*0Sstevel@tonic-gate */ 104*0Sstevel@tonic-gate ov = p->p_utraps[idx]; 105*0Sstevel@tonic-gate if (new_handler != (utrap_handler_t)UTRAP_UTH_NOCHANGE) { 106*0Sstevel@tonic-gate for (;;) { 107*0Sstevel@tonic-gate tmp = casptr(&p->p_utraps[idx], ov, nv); 108*0Sstevel@tonic-gate if (ov == tmp) 109*0Sstevel@tonic-gate break; 110*0Sstevel@tonic-gate ov = tmp; 111*0Sstevel@tonic-gate } 112*0Sstevel@tonic-gate } 113*0Sstevel@tonic-gate if (old_handlerp != NULL) { 114*0Sstevel@tonic-gate if (suword32(old_handlerp, (uint32_t)ov) == -1) 115*0Sstevel@tonic-gate return ((int)set_errno(EINVAL)); 116*0Sstevel@tonic-gate } 117*0Sstevel@tonic-gate return (0); 118*0Sstevel@tonic-gate } 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gate void 121*0Sstevel@tonic-gate utrap_dup(struct proc *pp, struct proc *cp) 122*0Sstevel@tonic-gate { 123*0Sstevel@tonic-gate if (pp->p_utraps != NULL) { 124*0Sstevel@tonic-gate cp->p_utraps = kmem_alloc((UT_PRECISE_MAXTRAPS+1) * 125*0Sstevel@tonic-gate sizeof (utrap_handler_t *), KM_SLEEP); 126*0Sstevel@tonic-gate bcopy(pp->p_utraps, cp->p_utraps, 127*0Sstevel@tonic-gate (UT_PRECISE_MAXTRAPS+1) * sizeof (utrap_handler_t *)); 128*0Sstevel@tonic-gate } else { 129*0Sstevel@tonic-gate cp->p_utraps = NULL; 130*0Sstevel@tonic-gate } 131*0Sstevel@tonic-gate } 132*0Sstevel@tonic-gate 133*0Sstevel@tonic-gate void 134*0Sstevel@tonic-gate utrap_free(struct proc *p) 135*0Sstevel@tonic-gate { 136*0Sstevel@tonic-gate /* Free any kmem_alloc'ed space for user trap handlers. */ 137*0Sstevel@tonic-gate if (p->p_utraps != NULL) { 138*0Sstevel@tonic-gate kmem_free(p->p_utraps, (UT_PRECISE_MAXTRAPS+1) * 139*0Sstevel@tonic-gate sizeof (utrap_handler_t *)); 140*0Sstevel@tonic-gate p->p_utraps = NULL; 141*0Sstevel@tonic-gate } 142*0Sstevel@tonic-gate } 143*0Sstevel@tonic-gate 144*0Sstevel@tonic-gate /* 145*0Sstevel@tonic-gate * The code below supports the set of user traps which are required and 146*0Sstevel@tonic-gate * "must be provided by all ABI-conforming implementations", according to 147*0Sstevel@tonic-gate * 3.3.3 User Traps of the SPARC V9 ABI SUPPLEMENT, Delta Document 1.38. 148*0Sstevel@tonic-gate * There is only 1 deferred trap in Ultra I&II, the asynchronous error 149*0Sstevel@tonic-gate * traps, which are not required, so the deferred args are not used. 150*0Sstevel@tonic-gate */ 151*0Sstevel@tonic-gate /*ARGSUSED*/ 152*0Sstevel@tonic-gate int 153*0Sstevel@tonic-gate sparc_utrap_install(utrap_entry_t type, 154*0Sstevel@tonic-gate utrap_handler_t new_precise, utrap_handler_t new_deferred, 155*0Sstevel@tonic-gate utrap_handler_t *old_precise, utrap_handler_t *old_deferred) 156*0Sstevel@tonic-gate { 157*0Sstevel@tonic-gate struct proc *p = curthread->t_procp; 158*0Sstevel@tonic-gate utrap_handler_t *ov, *nvp, *pv, *sv, *tmp; 159*0Sstevel@tonic-gate int idx; 160*0Sstevel@tonic-gate 161*0Sstevel@tonic-gate /* 162*0Sstevel@tonic-gate * Check trap number. 163*0Sstevel@tonic-gate */ 164*0Sstevel@tonic-gate switch (type) { 165*0Sstevel@tonic-gate case UT_ILLTRAP_INSTRUCTION: 166*0Sstevel@tonic-gate idx = UT_ILLTRAP_INSTRUCTION; 167*0Sstevel@tonic-gate break; 168*0Sstevel@tonic-gate case UT_FP_DISABLED: 169*0Sstevel@tonic-gate #ifdef SF_ERRATA_30 /* call causes fp-disabled */ 170*0Sstevel@tonic-gate { 171*0Sstevel@tonic-gate extern int spitfire_call_bug; 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate if (spitfire_call_bug) { 174*0Sstevel@tonic-gate cmn_err(CE_WARN, "UT_FP_DISABLED " 175*0Sstevel@tonic-gate "not supported for cpu version < 2.2"); 176*0Sstevel@tonic-gate return ((int)set_errno(ENOSYS)); 177*0Sstevel@tonic-gate } 178*0Sstevel@tonic-gate } 179*0Sstevel@tonic-gate #endif /* SF_ERRATA_30 */ 180*0Sstevel@tonic-gate idx = UT_FP_DISABLED; 181*0Sstevel@tonic-gate break; 182*0Sstevel@tonic-gate case UT_FP_EXCEPTION_IEEE_754: 183*0Sstevel@tonic-gate idx = UT_FP_EXCEPTION_IEEE_754; 184*0Sstevel@tonic-gate break; 185*0Sstevel@tonic-gate case UT_TAG_OVERFLOW: 186*0Sstevel@tonic-gate idx = UT_TAG_OVERFLOW; 187*0Sstevel@tonic-gate break; 188*0Sstevel@tonic-gate case UT_DIVISION_BY_ZERO: 189*0Sstevel@tonic-gate idx = UT_DIVISION_BY_ZERO; 190*0Sstevel@tonic-gate break; 191*0Sstevel@tonic-gate case UT_MEM_ADDRESS_NOT_ALIGNED: 192*0Sstevel@tonic-gate idx = UT_MEM_ADDRESS_NOT_ALIGNED; 193*0Sstevel@tonic-gate break; 194*0Sstevel@tonic-gate case UT_PRIVILEGED_ACTION: 195*0Sstevel@tonic-gate idx = UT_PRIVILEGED_ACTION; 196*0Sstevel@tonic-gate break; 197*0Sstevel@tonic-gate case UT_TRAP_INSTRUCTION_16: 198*0Sstevel@tonic-gate case UT_TRAP_INSTRUCTION_17: 199*0Sstevel@tonic-gate case UT_TRAP_INSTRUCTION_18: 200*0Sstevel@tonic-gate case UT_TRAP_INSTRUCTION_19: 201*0Sstevel@tonic-gate case UT_TRAP_INSTRUCTION_20: 202*0Sstevel@tonic-gate case UT_TRAP_INSTRUCTION_21: 203*0Sstevel@tonic-gate case UT_TRAP_INSTRUCTION_22: 204*0Sstevel@tonic-gate case UT_TRAP_INSTRUCTION_23: 205*0Sstevel@tonic-gate case UT_TRAP_INSTRUCTION_24: 206*0Sstevel@tonic-gate case UT_TRAP_INSTRUCTION_25: 207*0Sstevel@tonic-gate case UT_TRAP_INSTRUCTION_26: 208*0Sstevel@tonic-gate case UT_TRAP_INSTRUCTION_27: 209*0Sstevel@tonic-gate case UT_TRAP_INSTRUCTION_28: 210*0Sstevel@tonic-gate case UT_TRAP_INSTRUCTION_29: 211*0Sstevel@tonic-gate case UT_TRAP_INSTRUCTION_30: 212*0Sstevel@tonic-gate case UT_TRAP_INSTRUCTION_31: 213*0Sstevel@tonic-gate idx = type; 214*0Sstevel@tonic-gate break; 215*0Sstevel@tonic-gate default: 216*0Sstevel@tonic-gate return ((int)set_errno(EINVAL)); 217*0Sstevel@tonic-gate } 218*0Sstevel@tonic-gate 219*0Sstevel@tonic-gate if (get_udatamodel() == DATAMODEL_ILP32) { 220*0Sstevel@tonic-gate cmn_err(CE_WARN, "__sparc_utrap_install interface " 221*0Sstevel@tonic-gate "not supported for ILP32 user programs"); 222*0Sstevel@tonic-gate return ((int)set_errno(EINVAL)); 223*0Sstevel@tonic-gate } 224*0Sstevel@tonic-gate 225*0Sstevel@tonic-gate /* 226*0Sstevel@tonic-gate * Be sure handler address is word aligned. 227*0Sstevel@tonic-gate * There are no deferred traps, so ignore them. 228*0Sstevel@tonic-gate */ 229*0Sstevel@tonic-gate nvp = (utrap_handler_t *)new_precise; 230*0Sstevel@tonic-gate if (nvp != UTRAP_UTH_NOCHANGE) { 231*0Sstevel@tonic-gate if (((uintptr_t)nvp) & 0x3) 232*0Sstevel@tonic-gate return ((int)set_errno(EINVAL)); 233*0Sstevel@tonic-gate } 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gate /* 236*0Sstevel@tonic-gate * Allocate proc space for saving the addresses to these user 237*0Sstevel@tonic-gate * trap handlers, which must later be freed. Use casptr to 238*0Sstevel@tonic-gate * do this atomically. 239*0Sstevel@tonic-gate */ 240*0Sstevel@tonic-gate if (p->p_utraps == NULL) { 241*0Sstevel@tonic-gate pv = sv = kmem_zalloc((UT_PRECISE_MAXTRAPS+1) * 242*0Sstevel@tonic-gate sizeof (utrap_handler_t *), KM_SLEEP); 243*0Sstevel@tonic-gate tmp = casptr(&p->p_utraps, NULL, sv); 244*0Sstevel@tonic-gate if (tmp != NULL) { 245*0Sstevel@tonic-gate kmem_free(pv, (UT_PRECISE_MAXTRAPS+1) * 246*0Sstevel@tonic-gate sizeof (utrap_handler_t *)); 247*0Sstevel@tonic-gate } 248*0Sstevel@tonic-gate } 249*0Sstevel@tonic-gate ASSERT(p->p_utraps != NULL); 250*0Sstevel@tonic-gate 251*0Sstevel@tonic-gate /* 252*0Sstevel@tonic-gate * Use casptr to atomically install the handlers. 253*0Sstevel@tonic-gate */ 254*0Sstevel@tonic-gate ov = p->p_utraps[idx]; 255*0Sstevel@tonic-gate if (new_precise != (utrap_handler_t)UTH_NOCHANGE) { 256*0Sstevel@tonic-gate for (;;) { 257*0Sstevel@tonic-gate tmp = casptr(&p->p_utraps[idx], ov, nvp); 258*0Sstevel@tonic-gate if (ov == tmp) 259*0Sstevel@tonic-gate break; 260*0Sstevel@tonic-gate ov = tmp; 261*0Sstevel@tonic-gate } 262*0Sstevel@tonic-gate } 263*0Sstevel@tonic-gate if (old_precise != NULL) { 264*0Sstevel@tonic-gate if (suword64(old_precise, (uint64_t)ov) == -1) 265*0Sstevel@tonic-gate return ((int)set_errno(EINVAL)); 266*0Sstevel@tonic-gate } 267*0Sstevel@tonic-gate return (0); 268*0Sstevel@tonic-gate } 269