10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 52712Snn35248 * Common Development and Distribution License (the "License"). 62712Snn35248 * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*10797SEric.Saxe@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 270Sstevel@tonic-gate /* All Rights Reserved */ 280Sstevel@tonic-gate 290Sstevel@tonic-gate #include <sys/param.h> 300Sstevel@tonic-gate #include <sys/types.h> 310Sstevel@tonic-gate #include <sys/vmparam.h> 320Sstevel@tonic-gate #include <sys/systm.h> 330Sstevel@tonic-gate #include <sys/signal.h> 340Sstevel@tonic-gate #include <sys/stack.h> 350Sstevel@tonic-gate #include <sys/regset.h> 360Sstevel@tonic-gate #include <sys/privregs.h> 370Sstevel@tonic-gate #include <sys/frame.h> 380Sstevel@tonic-gate #include <sys/proc.h> 390Sstevel@tonic-gate #include <sys/psw.h> 400Sstevel@tonic-gate #include <sys/siginfo.h> 410Sstevel@tonic-gate #include <sys/cpuvar.h> 420Sstevel@tonic-gate #include <sys/asm_linkage.h> 430Sstevel@tonic-gate #include <sys/kmem.h> 440Sstevel@tonic-gate #include <sys/errno.h> 450Sstevel@tonic-gate #include <sys/bootconf.h> 460Sstevel@tonic-gate #include <sys/archsystm.h> 470Sstevel@tonic-gate #include <sys/debug.h> 480Sstevel@tonic-gate #include <sys/elf.h> 490Sstevel@tonic-gate #include <sys/spl.h> 500Sstevel@tonic-gate #include <sys/time.h> 510Sstevel@tonic-gate #include <sys/atomic.h> 520Sstevel@tonic-gate #include <sys/sysmacros.h> 530Sstevel@tonic-gate #include <sys/cmn_err.h> 540Sstevel@tonic-gate #include <sys/modctl.h> 550Sstevel@tonic-gate #include <sys/kobj.h> 560Sstevel@tonic-gate #include <sys/panic.h> 570Sstevel@tonic-gate #include <sys/reboot.h> 580Sstevel@tonic-gate #include <sys/time.h> 590Sstevel@tonic-gate #include <sys/fp.h> 600Sstevel@tonic-gate #include <sys/x86_archext.h> 610Sstevel@tonic-gate #include <sys/auxv.h> 620Sstevel@tonic-gate #include <sys/auxv_386.h> 630Sstevel@tonic-gate #include <sys/dtrace.h> 642712Snn35248 #include <sys/brand.h> 652712Snn35248 #include <sys/machbrand.h> 660Sstevel@tonic-gate 670Sstevel@tonic-gate extern const struct fnsave_state x87_initial; 680Sstevel@tonic-gate extern const struct fxsave_state sse_initial; 690Sstevel@tonic-gate 700Sstevel@tonic-gate /* 710Sstevel@tonic-gate * Map an fnsave-formatted save area into an fxsave-formatted save area. 720Sstevel@tonic-gate * 730Sstevel@tonic-gate * Most fields are the same width, content and semantics. However 740Sstevel@tonic-gate * the tag word is compressed. 750Sstevel@tonic-gate */ 760Sstevel@tonic-gate static void 770Sstevel@tonic-gate fnsave_to_fxsave(const struct fnsave_state *fn, struct fxsave_state *fx) 780Sstevel@tonic-gate { 790Sstevel@tonic-gate uint_t i, tagbits; 800Sstevel@tonic-gate 810Sstevel@tonic-gate fx->fx_fcw = fn->f_fcw; 820Sstevel@tonic-gate fx->fx_fsw = fn->f_fsw; 830Sstevel@tonic-gate 840Sstevel@tonic-gate /* 850Sstevel@tonic-gate * copy element by element (because of holes) 860Sstevel@tonic-gate */ 870Sstevel@tonic-gate for (i = 0; i < 8; i++) 880Sstevel@tonic-gate bcopy(&fn->f_st[i].fpr_16[0], &fx->fx_st[i].fpr_16[0], 890Sstevel@tonic-gate sizeof (fn->f_st[0].fpr_16)); /* 80-bit x87-style floats */ 900Sstevel@tonic-gate 910Sstevel@tonic-gate /* 920Sstevel@tonic-gate * synthesize compressed tag bits 930Sstevel@tonic-gate */ 940Sstevel@tonic-gate fx->fx_fctw = 0; 950Sstevel@tonic-gate for (tagbits = fn->f_ftw, i = 0; i < 8; i++, tagbits >>= 2) 960Sstevel@tonic-gate if ((tagbits & 3) != 3) 970Sstevel@tonic-gate fx->fx_fctw |= (1 << i); 980Sstevel@tonic-gate 990Sstevel@tonic-gate fx->fx_fop = fn->f_fop; 1000Sstevel@tonic-gate 1010Sstevel@tonic-gate #if defined(__amd64) 1020Sstevel@tonic-gate fx->fx_rip = (uint64_t)fn->f_eip; 1030Sstevel@tonic-gate fx->fx_rdp = (uint64_t)fn->f_dp; 1040Sstevel@tonic-gate #else 1050Sstevel@tonic-gate fx->fx_eip = fn->f_eip; 1060Sstevel@tonic-gate fx->fx_cs = fn->f_cs; 1070Sstevel@tonic-gate fx->__fx_ign0 = 0; 1080Sstevel@tonic-gate fx->fx_dp = fn->f_dp; 1090Sstevel@tonic-gate fx->fx_ds = fn->f_ds; 1100Sstevel@tonic-gate fx->__fx_ign1 = 0; 1110Sstevel@tonic-gate #endif 1120Sstevel@tonic-gate } 1130Sstevel@tonic-gate 1140Sstevel@tonic-gate /* 1150Sstevel@tonic-gate * Map from an fxsave-format save area to an fnsave-format save area. 1160Sstevel@tonic-gate */ 1170Sstevel@tonic-gate static void 1180Sstevel@tonic-gate fxsave_to_fnsave(const struct fxsave_state *fx, struct fnsave_state *fn) 1190Sstevel@tonic-gate { 1200Sstevel@tonic-gate uint_t i, top, tagbits; 1210Sstevel@tonic-gate 1220Sstevel@tonic-gate fn->f_fcw = fx->fx_fcw; 1230Sstevel@tonic-gate fn->__f_ign0 = 0; 1240Sstevel@tonic-gate fn->f_fsw = fx->fx_fsw; 1250Sstevel@tonic-gate fn->__f_ign1 = 0; 1260Sstevel@tonic-gate 1270Sstevel@tonic-gate top = (fx->fx_fsw & FPS_TOP) >> 11; 1280Sstevel@tonic-gate 1290Sstevel@tonic-gate /* 1300Sstevel@tonic-gate * copy element by element (because of holes) 1310Sstevel@tonic-gate */ 1320Sstevel@tonic-gate for (i = 0; i < 8; i++) 1330Sstevel@tonic-gate bcopy(&fx->fx_st[i].fpr_16[0], &fn->f_st[i].fpr_16[0], 1340Sstevel@tonic-gate sizeof (fn->f_st[0].fpr_16)); /* 80-bit x87-style floats */ 1350Sstevel@tonic-gate 1360Sstevel@tonic-gate /* 1370Sstevel@tonic-gate * synthesize uncompressed tag bits 1380Sstevel@tonic-gate */ 1390Sstevel@tonic-gate fn->f_ftw = 0; 1400Sstevel@tonic-gate for (tagbits = fx->fx_fctw, i = 0; i < 8; i++, tagbits >>= 1) { 1410Sstevel@tonic-gate uint_t ibit, expo; 1420Sstevel@tonic-gate const uint16_t *fpp; 1430Sstevel@tonic-gate static const uint16_t zero[5] = { 0, 0, 0, 0, 0 }; 1440Sstevel@tonic-gate 1450Sstevel@tonic-gate if ((tagbits & 1) == 0) { 1460Sstevel@tonic-gate fn->f_ftw |= 3 << (i << 1); /* empty */ 1470Sstevel@tonic-gate continue; 1480Sstevel@tonic-gate } 1490Sstevel@tonic-gate 1500Sstevel@tonic-gate /* 1510Sstevel@tonic-gate * (tags refer to *physical* registers) 1520Sstevel@tonic-gate */ 1530Sstevel@tonic-gate fpp = &fx->fx_st[(i - top + 8) & 7].fpr_16[0]; 1540Sstevel@tonic-gate ibit = fpp[3] >> 15; 1550Sstevel@tonic-gate expo = fpp[4] & 0x7fff; 1560Sstevel@tonic-gate 1570Sstevel@tonic-gate if (ibit && expo != 0 && expo != 0x7fff) 1580Sstevel@tonic-gate continue; /* valid fp number */ 1590Sstevel@tonic-gate 1600Sstevel@tonic-gate if (bcmp(fpp, &zero, sizeof (zero))) 1610Sstevel@tonic-gate fn->f_ftw |= 2 << (i << 1); /* NaN */ 1620Sstevel@tonic-gate else 1630Sstevel@tonic-gate fn->f_ftw |= 1 << (i << 1); /* fp zero */ 1640Sstevel@tonic-gate } 1650Sstevel@tonic-gate 1660Sstevel@tonic-gate fn->f_fop = fx->fx_fop; 1670Sstevel@tonic-gate 1680Sstevel@tonic-gate fn->__f_ign2 = 0; 1690Sstevel@tonic-gate #if defined(__amd64) 1700Sstevel@tonic-gate fn->f_eip = (uint32_t)fx->fx_rip; 1710Sstevel@tonic-gate fn->f_cs = U32CS_SEL; 1720Sstevel@tonic-gate fn->f_dp = (uint32_t)fx->fx_rdp; 1730Sstevel@tonic-gate fn->f_ds = UDS_SEL; 1740Sstevel@tonic-gate #else 1750Sstevel@tonic-gate fn->f_eip = fx->fx_eip; 1760Sstevel@tonic-gate fn->f_cs = fx->fx_cs; 1770Sstevel@tonic-gate fn->f_dp = fx->fx_dp; 1780Sstevel@tonic-gate fn->f_ds = fx->fx_ds; 1790Sstevel@tonic-gate #endif 1800Sstevel@tonic-gate fn->__f_ign3 = 0; 1810Sstevel@tonic-gate } 1820Sstevel@tonic-gate 1830Sstevel@tonic-gate /* 1840Sstevel@tonic-gate * Map from an fpregset_t into an fxsave-format save area 1850Sstevel@tonic-gate */ 1860Sstevel@tonic-gate static void 1870Sstevel@tonic-gate fpregset_to_fxsave(const fpregset_t *fp, struct fxsave_state *fx) 1880Sstevel@tonic-gate { 1890Sstevel@tonic-gate #if defined(__amd64) 1900Sstevel@tonic-gate bcopy(fp, fx, sizeof (*fx)); 1910Sstevel@tonic-gate #else 1920Sstevel@tonic-gate const struct fpchip_state *fc = &fp->fp_reg_set.fpchip_state; 1930Sstevel@tonic-gate 1940Sstevel@tonic-gate fnsave_to_fxsave((const struct fnsave_state *)fc, fx); 1950Sstevel@tonic-gate fx->fx_mxcsr = fc->mxcsr; 1960Sstevel@tonic-gate bcopy(&fc->xmm[0], &fx->fx_xmm[0], sizeof (fc->xmm)); 1970Sstevel@tonic-gate #endif 1980Sstevel@tonic-gate /* 1990Sstevel@tonic-gate * avoid useless #gp exceptions - mask reserved bits 2000Sstevel@tonic-gate */ 2010Sstevel@tonic-gate fx->fx_mxcsr &= sse_mxcsr_mask; 2020Sstevel@tonic-gate } 2030Sstevel@tonic-gate 2040Sstevel@tonic-gate /* 2050Sstevel@tonic-gate * Map from an fxsave-format save area into a fpregset_t 2060Sstevel@tonic-gate */ 2070Sstevel@tonic-gate static void 2080Sstevel@tonic-gate fxsave_to_fpregset(const struct fxsave_state *fx, fpregset_t *fp) 2090Sstevel@tonic-gate { 2100Sstevel@tonic-gate #if defined(__amd64) 2110Sstevel@tonic-gate bcopy(fx, fp, sizeof (*fx)); 2120Sstevel@tonic-gate #else 2130Sstevel@tonic-gate struct fpchip_state *fc = &fp->fp_reg_set.fpchip_state; 2140Sstevel@tonic-gate 2150Sstevel@tonic-gate fxsave_to_fnsave(fx, (struct fnsave_state *)fc); 2160Sstevel@tonic-gate fc->mxcsr = fx->fx_mxcsr; 2170Sstevel@tonic-gate bcopy(&fx->fx_xmm[0], &fc->xmm[0], sizeof (fc->xmm)); 2180Sstevel@tonic-gate #endif 2190Sstevel@tonic-gate } 2200Sstevel@tonic-gate 2210Sstevel@tonic-gate #if defined(_SYSCALL32_IMPL) 2220Sstevel@tonic-gate static void 2230Sstevel@tonic-gate fpregset32_to_fxsave(const fpregset32_t *fp, struct fxsave_state *fx) 2240Sstevel@tonic-gate { 2250Sstevel@tonic-gate const struct fpchip32_state *fc = &fp->fp_reg_set.fpchip_state; 2260Sstevel@tonic-gate 2270Sstevel@tonic-gate fnsave_to_fxsave((const struct fnsave_state *)fc, fx); 2280Sstevel@tonic-gate /* 2290Sstevel@tonic-gate * avoid useless #gp exceptions - mask reserved bits 2300Sstevel@tonic-gate */ 2310Sstevel@tonic-gate fx->fx_mxcsr = sse_mxcsr_mask & fc->mxcsr; 2320Sstevel@tonic-gate bcopy(&fc->xmm[0], &fx->fx_xmm[0], sizeof (fc->xmm)); 2330Sstevel@tonic-gate } 2340Sstevel@tonic-gate 2350Sstevel@tonic-gate static void 2360Sstevel@tonic-gate fxsave_to_fpregset32(const struct fxsave_state *fx, fpregset32_t *fp) 2370Sstevel@tonic-gate { 2380Sstevel@tonic-gate struct fpchip32_state *fc = &fp->fp_reg_set.fpchip_state; 2390Sstevel@tonic-gate 2400Sstevel@tonic-gate fxsave_to_fnsave(fx, (struct fnsave_state *)fc); 2410Sstevel@tonic-gate fc->mxcsr = fx->fx_mxcsr; 2420Sstevel@tonic-gate bcopy(&fx->fx_xmm[0], &fc->xmm[0], sizeof (fc->xmm)); 2430Sstevel@tonic-gate } 2440Sstevel@tonic-gate 2450Sstevel@tonic-gate static void 2460Sstevel@tonic-gate fpregset_nto32(const fpregset_t *src, fpregset32_t *dst) 2470Sstevel@tonic-gate { 2480Sstevel@tonic-gate fxsave_to_fpregset32((struct fxsave_state *)src, dst); 2490Sstevel@tonic-gate dst->fp_reg_set.fpchip_state.status = 2500Sstevel@tonic-gate src->fp_reg_set.fpchip_state.status; 2510Sstevel@tonic-gate dst->fp_reg_set.fpchip_state.xstatus = 2520Sstevel@tonic-gate src->fp_reg_set.fpchip_state.xstatus; 2530Sstevel@tonic-gate } 2540Sstevel@tonic-gate 2550Sstevel@tonic-gate static void 2560Sstevel@tonic-gate fpregset_32ton(const fpregset32_t *src, fpregset_t *dst) 2570Sstevel@tonic-gate { 2580Sstevel@tonic-gate fpregset32_to_fxsave(src, (struct fxsave_state *)dst); 2590Sstevel@tonic-gate dst->fp_reg_set.fpchip_state.status = 2600Sstevel@tonic-gate src->fp_reg_set.fpchip_state.status; 2610Sstevel@tonic-gate dst->fp_reg_set.fpchip_state.xstatus = 2620Sstevel@tonic-gate src->fp_reg_set.fpchip_state.xstatus; 2630Sstevel@tonic-gate } 2640Sstevel@tonic-gate #endif 2650Sstevel@tonic-gate 2660Sstevel@tonic-gate /* 2670Sstevel@tonic-gate * Set floating-point registers from a native fpregset_t. 2680Sstevel@tonic-gate */ 2690Sstevel@tonic-gate void 2700Sstevel@tonic-gate setfpregs(klwp_t *lwp, fpregset_t *fp) 2710Sstevel@tonic-gate { 2720Sstevel@tonic-gate struct fpu_ctx *fpu = &lwp->lwp_pcb.pcb_fpu; 2730Sstevel@tonic-gate 2740Sstevel@tonic-gate if (fpu->fpu_flags & FPU_EN) { 2750Sstevel@tonic-gate if (!(fpu->fpu_flags & FPU_VALID)) { 2760Sstevel@tonic-gate /* 2770Sstevel@tonic-gate * FPU context is still active, release the 2780Sstevel@tonic-gate * ownership. 2790Sstevel@tonic-gate */ 2800Sstevel@tonic-gate fp_free(fpu, 0); 2810Sstevel@tonic-gate } 2820Sstevel@tonic-gate #if !defined(__amd64) 2830Sstevel@tonic-gate if (fp_kind == __FP_SSE) { 2840Sstevel@tonic-gate #endif 2850Sstevel@tonic-gate fpregset_to_fxsave(fp, &fpu->fpu_regs.kfpu_u.kfpu_fx); 2860Sstevel@tonic-gate fpu->fpu_regs.kfpu_xstatus = 2870Sstevel@tonic-gate fp->fp_reg_set.fpchip_state.xstatus; 2880Sstevel@tonic-gate #if !defined(__amd64) 2890Sstevel@tonic-gate } else 2900Sstevel@tonic-gate bcopy(fp, &fpu->fpu_regs.kfpu_u.kfpu_fn, 2910Sstevel@tonic-gate sizeof (fpu->fpu_regs.kfpu_u.kfpu_fn)); 2920Sstevel@tonic-gate #endif 2930Sstevel@tonic-gate fpu->fpu_regs.kfpu_status = fp->fp_reg_set.fpchip_state.status; 2940Sstevel@tonic-gate fpu->fpu_flags |= FPU_VALID; 2950Sstevel@tonic-gate } else { 2960Sstevel@tonic-gate /* 2970Sstevel@tonic-gate * If we are trying to change the FPU state of a thread which 2980Sstevel@tonic-gate * hasn't yet initialized floating point, store the state in 2990Sstevel@tonic-gate * the pcb and indicate that the state is valid. When the 3000Sstevel@tonic-gate * thread enables floating point, it will use this state instead 3010Sstevel@tonic-gate * of the default state. 3020Sstevel@tonic-gate */ 3030Sstevel@tonic-gate #if !defined(__amd64) 3040Sstevel@tonic-gate if (fp_kind == __FP_SSE) { 3050Sstevel@tonic-gate #endif 3060Sstevel@tonic-gate fpregset_to_fxsave(fp, &fpu->fpu_regs.kfpu_u.kfpu_fx); 3070Sstevel@tonic-gate fpu->fpu_regs.kfpu_xstatus = 3080Sstevel@tonic-gate fp->fp_reg_set.fpchip_state.xstatus; 3090Sstevel@tonic-gate #if !defined(__amd64) 3100Sstevel@tonic-gate } else 3110Sstevel@tonic-gate bcopy(fp, &fpu->fpu_regs.kfpu_u.kfpu_fn, 3120Sstevel@tonic-gate sizeof (fpu->fpu_regs.kfpu_u.kfpu_fn)); 3130Sstevel@tonic-gate #endif 3140Sstevel@tonic-gate fpu->fpu_regs.kfpu_status = fp->fp_reg_set.fpchip_state.status; 3150Sstevel@tonic-gate fpu->fpu_flags |= FPU_VALID; 3160Sstevel@tonic-gate } 3170Sstevel@tonic-gate } 3180Sstevel@tonic-gate 3190Sstevel@tonic-gate /* 3200Sstevel@tonic-gate * Get floating-point registers into a native fpregset_t. 3210Sstevel@tonic-gate */ 3220Sstevel@tonic-gate void 3230Sstevel@tonic-gate getfpregs(klwp_t *lwp, fpregset_t *fp) 3240Sstevel@tonic-gate { 3250Sstevel@tonic-gate struct fpu_ctx *fpu = &lwp->lwp_pcb.pcb_fpu; 3260Sstevel@tonic-gate 3270Sstevel@tonic-gate kpreempt_disable(); 3280Sstevel@tonic-gate if (fpu->fpu_flags & FPU_EN) { 3290Sstevel@tonic-gate /* 3300Sstevel@tonic-gate * If we have FPU hw and the thread's pcb doesn't have 3310Sstevel@tonic-gate * a valid FPU state then get the state from the hw. 3320Sstevel@tonic-gate */ 3330Sstevel@tonic-gate if (fpu_exists && ttolwp(curthread) == lwp && 3340Sstevel@tonic-gate !(fpu->fpu_flags & FPU_VALID)) 3350Sstevel@tonic-gate fp_save(fpu); /* get the current FPU state */ 3360Sstevel@tonic-gate } 3370Sstevel@tonic-gate 3380Sstevel@tonic-gate /* 3390Sstevel@tonic-gate * There are 3 possible cases we have to be aware of here: 3400Sstevel@tonic-gate * 3410Sstevel@tonic-gate * 1. FPU is enabled. FPU state is stored in the current LWP. 3420Sstevel@tonic-gate * 3430Sstevel@tonic-gate * 2. FPU is not enabled, and there have been no intervening /proc 3440Sstevel@tonic-gate * modifications. Return initial FPU state. 3450Sstevel@tonic-gate * 3460Sstevel@tonic-gate * 3. FPU is not enabled, but a /proc consumer has modified FPU state. 3470Sstevel@tonic-gate * FPU state is stored in the current LWP. 3480Sstevel@tonic-gate */ 3490Sstevel@tonic-gate if ((fpu->fpu_flags & FPU_EN) || (fpu->fpu_flags & FPU_VALID)) { 3500Sstevel@tonic-gate /* 3510Sstevel@tonic-gate * Cases 1 and 3. 3520Sstevel@tonic-gate */ 3530Sstevel@tonic-gate #if !defined(__amd64) 3540Sstevel@tonic-gate if (fp_kind == __FP_SSE) { 3550Sstevel@tonic-gate #endif 3560Sstevel@tonic-gate fxsave_to_fpregset(&fpu->fpu_regs.kfpu_u.kfpu_fx, fp); 3570Sstevel@tonic-gate fp->fp_reg_set.fpchip_state.xstatus = 3580Sstevel@tonic-gate fpu->fpu_regs.kfpu_xstatus; 3590Sstevel@tonic-gate #if !defined(__amd64) 3600Sstevel@tonic-gate } else 3610Sstevel@tonic-gate bcopy(&fpu->fpu_regs.kfpu_u.kfpu_fn, fp, 3620Sstevel@tonic-gate sizeof (fpu->fpu_regs.kfpu_u.kfpu_fn)); 3630Sstevel@tonic-gate #endif 3640Sstevel@tonic-gate fp->fp_reg_set.fpchip_state.status = fpu->fpu_regs.kfpu_status; 3650Sstevel@tonic-gate } else { 3660Sstevel@tonic-gate /* 3670Sstevel@tonic-gate * Case 2. 3680Sstevel@tonic-gate */ 3690Sstevel@tonic-gate #if !defined(__amd64) 3700Sstevel@tonic-gate if (fp_kind == __FP_SSE) { 3710Sstevel@tonic-gate #endif 3720Sstevel@tonic-gate fxsave_to_fpregset(&sse_initial, fp); 3730Sstevel@tonic-gate fp->fp_reg_set.fpchip_state.xstatus = 3740Sstevel@tonic-gate fpu->fpu_regs.kfpu_xstatus; 3750Sstevel@tonic-gate #if !defined(__amd64) 3760Sstevel@tonic-gate } else 3770Sstevel@tonic-gate bcopy(&x87_initial, fp, sizeof (x87_initial)); 3780Sstevel@tonic-gate #endif 3790Sstevel@tonic-gate fp->fp_reg_set.fpchip_state.status = fpu->fpu_regs.kfpu_status; 3800Sstevel@tonic-gate } 3810Sstevel@tonic-gate kpreempt_enable(); 3820Sstevel@tonic-gate } 3830Sstevel@tonic-gate 3840Sstevel@tonic-gate #if defined(_SYSCALL32_IMPL) 3850Sstevel@tonic-gate 3860Sstevel@tonic-gate /* 3870Sstevel@tonic-gate * Set floating-point registers from an fpregset32_t. 3880Sstevel@tonic-gate */ 3890Sstevel@tonic-gate void 3900Sstevel@tonic-gate setfpregs32(klwp_t *lwp, fpregset32_t *fp) 3910Sstevel@tonic-gate { 3920Sstevel@tonic-gate fpregset_t fpregs; 3930Sstevel@tonic-gate 3940Sstevel@tonic-gate fpregset_32ton(fp, &fpregs); 3950Sstevel@tonic-gate setfpregs(lwp, &fpregs); 3960Sstevel@tonic-gate } 3970Sstevel@tonic-gate 3980Sstevel@tonic-gate /* 3990Sstevel@tonic-gate * Get floating-point registers into an fpregset32_t. 4000Sstevel@tonic-gate */ 4010Sstevel@tonic-gate void 4020Sstevel@tonic-gate getfpregs32(klwp_t *lwp, fpregset32_t *fp) 4030Sstevel@tonic-gate { 4040Sstevel@tonic-gate fpregset_t fpregs; 4050Sstevel@tonic-gate 4060Sstevel@tonic-gate getfpregs(lwp, &fpregs); 4070Sstevel@tonic-gate fpregset_nto32(&fpregs, fp); 4080Sstevel@tonic-gate } 4090Sstevel@tonic-gate 4100Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 4110Sstevel@tonic-gate 4120Sstevel@tonic-gate /* 4130Sstevel@tonic-gate * Return the general registers 4140Sstevel@tonic-gate */ 4150Sstevel@tonic-gate void 4160Sstevel@tonic-gate getgregs(klwp_t *lwp, gregset_t grp) 4170Sstevel@tonic-gate { 4180Sstevel@tonic-gate struct regs *rp = lwptoregs(lwp); 4190Sstevel@tonic-gate #if defined(__amd64) 4200Sstevel@tonic-gate struct pcb *pcb = &lwp->lwp_pcb; 4210Sstevel@tonic-gate int thisthread = lwptot(lwp) == curthread; 4220Sstevel@tonic-gate 4230Sstevel@tonic-gate grp[REG_RDI] = rp->r_rdi; 4240Sstevel@tonic-gate grp[REG_RSI] = rp->r_rsi; 4250Sstevel@tonic-gate grp[REG_RDX] = rp->r_rdx; 4260Sstevel@tonic-gate grp[REG_RCX] = rp->r_rcx; 4270Sstevel@tonic-gate grp[REG_R8] = rp->r_r8; 4280Sstevel@tonic-gate grp[REG_R9] = rp->r_r9; 4290Sstevel@tonic-gate grp[REG_RAX] = rp->r_rax; 4300Sstevel@tonic-gate grp[REG_RBX] = rp->r_rbx; 4310Sstevel@tonic-gate grp[REG_RBP] = rp->r_rbp; 4320Sstevel@tonic-gate grp[REG_R10] = rp->r_r10; 4330Sstevel@tonic-gate grp[REG_R11] = rp->r_r11; 4340Sstevel@tonic-gate grp[REG_R12] = rp->r_r12; 4350Sstevel@tonic-gate grp[REG_R13] = rp->r_r13; 4360Sstevel@tonic-gate grp[REG_R14] = rp->r_r14; 4370Sstevel@tonic-gate grp[REG_R15] = rp->r_r15; 4380Sstevel@tonic-gate grp[REG_FSBASE] = pcb->pcb_fsbase; 4390Sstevel@tonic-gate grp[REG_GSBASE] = pcb->pcb_gsbase; 4400Sstevel@tonic-gate if (thisthread) 4410Sstevel@tonic-gate kpreempt_disable(); 4424503Ssudheer if (pcb->pcb_rupdate == 1) { 4430Sstevel@tonic-gate grp[REG_DS] = pcb->pcb_ds; 4440Sstevel@tonic-gate grp[REG_ES] = pcb->pcb_es; 4450Sstevel@tonic-gate grp[REG_FS] = pcb->pcb_fs; 4460Sstevel@tonic-gate grp[REG_GS] = pcb->pcb_gs; 4470Sstevel@tonic-gate } else { 4480Sstevel@tonic-gate grp[REG_DS] = rp->r_ds; 4490Sstevel@tonic-gate grp[REG_ES] = rp->r_es; 4500Sstevel@tonic-gate grp[REG_FS] = rp->r_fs; 4510Sstevel@tonic-gate grp[REG_GS] = rp->r_gs; 4520Sstevel@tonic-gate } 4530Sstevel@tonic-gate if (thisthread) 4540Sstevel@tonic-gate kpreempt_enable(); 4550Sstevel@tonic-gate grp[REG_TRAPNO] = rp->r_trapno; 4560Sstevel@tonic-gate grp[REG_ERR] = rp->r_err; 4570Sstevel@tonic-gate grp[REG_RIP] = rp->r_rip; 4580Sstevel@tonic-gate grp[REG_CS] = rp->r_cs; 4590Sstevel@tonic-gate grp[REG_SS] = rp->r_ss; 4600Sstevel@tonic-gate grp[REG_RFL] = rp->r_rfl; 4610Sstevel@tonic-gate grp[REG_RSP] = rp->r_rsp; 4620Sstevel@tonic-gate #else 4630Sstevel@tonic-gate bcopy(&rp->r_gs, grp, sizeof (gregset_t)); 4640Sstevel@tonic-gate #endif 4650Sstevel@tonic-gate } 4660Sstevel@tonic-gate 4670Sstevel@tonic-gate #if defined(_SYSCALL32_IMPL) 4680Sstevel@tonic-gate 4690Sstevel@tonic-gate void 4700Sstevel@tonic-gate getgregs32(klwp_t *lwp, gregset32_t grp) 4710Sstevel@tonic-gate { 4720Sstevel@tonic-gate struct regs *rp = lwptoregs(lwp); 4730Sstevel@tonic-gate struct pcb *pcb = &lwp->lwp_pcb; 4740Sstevel@tonic-gate int thisthread = lwptot(lwp) == curthread; 4750Sstevel@tonic-gate 4760Sstevel@tonic-gate if (thisthread) 4770Sstevel@tonic-gate kpreempt_disable(); 4784503Ssudheer if (pcb->pcb_rupdate == 1) { 4790Sstevel@tonic-gate grp[GS] = (uint16_t)pcb->pcb_gs; 4800Sstevel@tonic-gate grp[FS] = (uint16_t)pcb->pcb_fs; 4810Sstevel@tonic-gate grp[DS] = (uint16_t)pcb->pcb_ds; 4820Sstevel@tonic-gate grp[ES] = (uint16_t)pcb->pcb_es; 4830Sstevel@tonic-gate } else { 4840Sstevel@tonic-gate grp[GS] = (uint16_t)rp->r_gs; 4850Sstevel@tonic-gate grp[FS] = (uint16_t)rp->r_fs; 4860Sstevel@tonic-gate grp[DS] = (uint16_t)rp->r_ds; 4870Sstevel@tonic-gate grp[ES] = (uint16_t)rp->r_es; 4880Sstevel@tonic-gate } 4890Sstevel@tonic-gate if (thisthread) 4900Sstevel@tonic-gate kpreempt_enable(); 4910Sstevel@tonic-gate grp[EDI] = (greg32_t)rp->r_rdi; 4920Sstevel@tonic-gate grp[ESI] = (greg32_t)rp->r_rsi; 4930Sstevel@tonic-gate grp[EBP] = (greg32_t)rp->r_rbp; 4940Sstevel@tonic-gate grp[ESP] = 0; 4950Sstevel@tonic-gate grp[EBX] = (greg32_t)rp->r_rbx; 4960Sstevel@tonic-gate grp[EDX] = (greg32_t)rp->r_rdx; 4970Sstevel@tonic-gate grp[ECX] = (greg32_t)rp->r_rcx; 4980Sstevel@tonic-gate grp[EAX] = (greg32_t)rp->r_rax; 4990Sstevel@tonic-gate grp[TRAPNO] = (greg32_t)rp->r_trapno; 5000Sstevel@tonic-gate grp[ERR] = (greg32_t)rp->r_err; 5010Sstevel@tonic-gate grp[EIP] = (greg32_t)rp->r_rip; 5020Sstevel@tonic-gate grp[CS] = (uint16_t)rp->r_cs; 5030Sstevel@tonic-gate grp[EFL] = (greg32_t)rp->r_rfl; 5040Sstevel@tonic-gate grp[UESP] = (greg32_t)rp->r_rsp; 5050Sstevel@tonic-gate grp[SS] = (uint16_t)rp->r_ss; 5060Sstevel@tonic-gate } 5070Sstevel@tonic-gate 5080Sstevel@tonic-gate void 5090Sstevel@tonic-gate ucontext_32ton(const ucontext32_t *src, ucontext_t *dst) 5100Sstevel@tonic-gate { 5110Sstevel@tonic-gate mcontext_t *dmc = &dst->uc_mcontext; 5120Sstevel@tonic-gate const mcontext32_t *smc = &src->uc_mcontext; 5130Sstevel@tonic-gate 5140Sstevel@tonic-gate bzero(dst, sizeof (*dst)); 5150Sstevel@tonic-gate dst->uc_flags = src->uc_flags; 5160Sstevel@tonic-gate dst->uc_link = (ucontext_t *)(uintptr_t)src->uc_link; 5170Sstevel@tonic-gate 5180Sstevel@tonic-gate bcopy(&src->uc_sigmask, &dst->uc_sigmask, sizeof (dst->uc_sigmask)); 5190Sstevel@tonic-gate 5200Sstevel@tonic-gate dst->uc_stack.ss_sp = (void *)(uintptr_t)src->uc_stack.ss_sp; 5210Sstevel@tonic-gate dst->uc_stack.ss_size = (size_t)src->uc_stack.ss_size; 5220Sstevel@tonic-gate dst->uc_stack.ss_flags = src->uc_stack.ss_flags; 5230Sstevel@tonic-gate 5240Sstevel@tonic-gate dmc->gregs[REG_GS] = (greg_t)(uint32_t)smc->gregs[GS]; 5250Sstevel@tonic-gate dmc->gregs[REG_FS] = (greg_t)(uint32_t)smc->gregs[FS]; 5260Sstevel@tonic-gate dmc->gregs[REG_ES] = (greg_t)(uint32_t)smc->gregs[ES]; 5270Sstevel@tonic-gate dmc->gregs[REG_DS] = (greg_t)(uint32_t)smc->gregs[DS]; 5280Sstevel@tonic-gate dmc->gregs[REG_RDI] = (greg_t)(uint32_t)smc->gregs[EDI]; 5290Sstevel@tonic-gate dmc->gregs[REG_RSI] = (greg_t)(uint32_t)smc->gregs[ESI]; 5300Sstevel@tonic-gate dmc->gregs[REG_RBP] = (greg_t)(uint32_t)smc->gregs[EBP]; 5310Sstevel@tonic-gate dmc->gregs[REG_RBX] = (greg_t)(uint32_t)smc->gregs[EBX]; 5320Sstevel@tonic-gate dmc->gregs[REG_RDX] = (greg_t)(uint32_t)smc->gregs[EDX]; 5330Sstevel@tonic-gate dmc->gregs[REG_RCX] = (greg_t)(uint32_t)smc->gregs[ECX]; 5340Sstevel@tonic-gate dmc->gregs[REG_RAX] = (greg_t)(uint32_t)smc->gregs[EAX]; 5350Sstevel@tonic-gate dmc->gregs[REG_TRAPNO] = (greg_t)(uint32_t)smc->gregs[TRAPNO]; 5360Sstevel@tonic-gate dmc->gregs[REG_ERR] = (greg_t)(uint32_t)smc->gregs[ERR]; 5370Sstevel@tonic-gate dmc->gregs[REG_RIP] = (greg_t)(uint32_t)smc->gregs[EIP]; 5380Sstevel@tonic-gate dmc->gregs[REG_CS] = (greg_t)(uint32_t)smc->gregs[CS]; 5390Sstevel@tonic-gate dmc->gregs[REG_RFL] = (greg_t)(uint32_t)smc->gregs[EFL]; 5400Sstevel@tonic-gate dmc->gregs[REG_RSP] = (greg_t)(uint32_t)smc->gregs[UESP]; 5410Sstevel@tonic-gate dmc->gregs[REG_SS] = (greg_t)(uint32_t)smc->gregs[SS]; 5420Sstevel@tonic-gate 5430Sstevel@tonic-gate /* 5440Sstevel@tonic-gate * A valid fpregs is only copied in if uc.uc_flags has UC_FPU set 5450Sstevel@tonic-gate * otherwise there is no guarantee that anything in fpregs is valid. 5460Sstevel@tonic-gate */ 5470Sstevel@tonic-gate if (src->uc_flags & UC_FPU) 5480Sstevel@tonic-gate fpregset_32ton(&src->uc_mcontext.fpregs, 5490Sstevel@tonic-gate &dst->uc_mcontext.fpregs); 5500Sstevel@tonic-gate } 5510Sstevel@tonic-gate 5520Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 5530Sstevel@tonic-gate 5540Sstevel@tonic-gate /* 5550Sstevel@tonic-gate * Return the user-level PC. 5560Sstevel@tonic-gate * If in a system call, return the address of the syscall trap. 5570Sstevel@tonic-gate */ 5580Sstevel@tonic-gate greg_t 5590Sstevel@tonic-gate getuserpc() 5600Sstevel@tonic-gate { 5610Sstevel@tonic-gate greg_t upc = lwptoregs(ttolwp(curthread))->r_pc; 5620Sstevel@tonic-gate uint32_t insn; 5630Sstevel@tonic-gate 5640Sstevel@tonic-gate if (curthread->t_sysnum == 0) 5650Sstevel@tonic-gate return (upc); 5660Sstevel@tonic-gate 5670Sstevel@tonic-gate /* 5680Sstevel@tonic-gate * We might've gotten here from sysenter (0xf 0x34), 5690Sstevel@tonic-gate * syscall (0xf 0x5) or lcall (0x9a 0 0 0 0 0x27 0). 5700Sstevel@tonic-gate * 5710Sstevel@tonic-gate * Go peek at the binary to figure it out.. 5720Sstevel@tonic-gate */ 5730Sstevel@tonic-gate if (fuword32((void *)(upc - 2), &insn) != -1 && 5740Sstevel@tonic-gate (insn & 0xffff) == 0x340f || (insn & 0xffff) == 0x050f) 5750Sstevel@tonic-gate return (upc - 2); 5760Sstevel@tonic-gate return (upc - 7); 5770Sstevel@tonic-gate } 5780Sstevel@tonic-gate 5790Sstevel@tonic-gate /* 5800Sstevel@tonic-gate * Protect segment registers from non-user privilege levels and GDT selectors 5810Sstevel@tonic-gate * other than USER_CS, USER_DS and lwp FS and GS values. If the segment 5820Sstevel@tonic-gate * selector is non-null and not USER_CS/USER_DS, we make sure that the 5830Sstevel@tonic-gate * TI bit is set to point into the LDT and that the RPL is set to 3. 5840Sstevel@tonic-gate * 5850Sstevel@tonic-gate * Since struct regs stores each 16-bit segment register as a 32-bit greg_t, we 5860Sstevel@tonic-gate * also explicitly zero the top 16 bits since they may be coming from the 5870Sstevel@tonic-gate * user's address space via setcontext(2) or /proc. 5885084Sjohnlev * 5895084Sjohnlev * Note about null selector. When running on the hypervisor if we allow a 5905084Sjohnlev * process to set its %cs to null selector with RPL of 0 the hypervisor will 5915084Sjohnlev * crash the domain. If running on bare metal we would get a #gp fault and 5925084Sjohnlev * be able to kill the process and continue on. Therefore we make sure to 5935084Sjohnlev * force RPL to SEL_UPL even for null selector when setting %cs. 5940Sstevel@tonic-gate */ 5950Sstevel@tonic-gate 5965084Sjohnlev #if defined(IS_CS) || defined(IS_NOT_CS) 5975084Sjohnlev #error "IS_CS and IS_NOT_CS already defined" 5985084Sjohnlev #endif 5995084Sjohnlev 6005084Sjohnlev #define IS_CS 1 6015084Sjohnlev #define IS_NOT_CS 0 6025084Sjohnlev 6030Sstevel@tonic-gate /*ARGSUSED*/ 6040Sstevel@tonic-gate static greg_t 6055084Sjohnlev fix_segreg(greg_t sr, int iscs, model_t datamodel) 6060Sstevel@tonic-gate { 6072712Snn35248 kthread_t *t = curthread; 6082712Snn35248 6090Sstevel@tonic-gate switch (sr &= 0xffff) { 6105084Sjohnlev 6115084Sjohnlev case 0: 6125084Sjohnlev if (iscs == IS_CS) 6135084Sjohnlev return (0 | SEL_UPL); 6145084Sjohnlev else 6155084Sjohnlev return (0); 6165084Sjohnlev 6170Sstevel@tonic-gate #if defined(__amd64) 6180Sstevel@tonic-gate /* 6190Sstevel@tonic-gate * If lwp attempts to switch data model then force their 6200Sstevel@tonic-gate * code selector to be null selector. 6210Sstevel@tonic-gate */ 6220Sstevel@tonic-gate case U32CS_SEL: 6230Sstevel@tonic-gate if (datamodel == DATAMODEL_NATIVE) 6245084Sjohnlev return (0 | SEL_UPL); 6250Sstevel@tonic-gate else 6260Sstevel@tonic-gate return (sr); 6270Sstevel@tonic-gate 6280Sstevel@tonic-gate case UCS_SEL: 6290Sstevel@tonic-gate if (datamodel == DATAMODEL_ILP32) 6305084Sjohnlev return (0 | SEL_UPL); 6310Sstevel@tonic-gate #elif defined(__i386) 6320Sstevel@tonic-gate case UCS_SEL: 6330Sstevel@tonic-gate #endif 6340Sstevel@tonic-gate /*FALLTHROUGH*/ 6350Sstevel@tonic-gate case UDS_SEL: 6360Sstevel@tonic-gate case LWPFS_SEL: 6370Sstevel@tonic-gate case LWPGS_SEL: 6385084Sjohnlev case SEL_UPL: 6390Sstevel@tonic-gate return (sr); 6400Sstevel@tonic-gate default: 6410Sstevel@tonic-gate break; 6420Sstevel@tonic-gate } 6430Sstevel@tonic-gate 6440Sstevel@tonic-gate /* 6452712Snn35248 * Allow this process's brand to do any necessary segment register 6462712Snn35248 * manipulation. 6472712Snn35248 */ 6485084Sjohnlev if (PROC_IS_BRANDED(t->t_procp) && BRMOP(t->t_procp)->b_fixsegreg) { 6495084Sjohnlev greg_t bsr = BRMOP(t->t_procp)->b_fixsegreg(sr, datamodel); 6505084Sjohnlev 6515084Sjohnlev if (bsr == 0 && iscs == IS_CS) 6525084Sjohnlev return (0 | SEL_UPL); 6535084Sjohnlev else 6545084Sjohnlev return (bsr); 6555084Sjohnlev } 6562712Snn35248 6572712Snn35248 /* 6581217Srab * Force it into the LDT in ring 3 for 32-bit processes, which by 6591217Srab * default do not have an LDT, so that any attempt to use an invalid 6605084Sjohnlev * selector will reference the (non-existant) LDT, and cause a #gp 6615084Sjohnlev * fault for the process. 6621217Srab * 6630Sstevel@tonic-gate * 64-bit processes get the null gdt selector since they 6640Sstevel@tonic-gate * are not allowed to have a private LDT. 6650Sstevel@tonic-gate */ 6660Sstevel@tonic-gate #if defined(__amd64) 6675084Sjohnlev if (datamodel == DATAMODEL_ILP32) { 6685084Sjohnlev return (sr | SEL_TI_LDT | SEL_UPL); 6695084Sjohnlev } else { 6705084Sjohnlev if (iscs == IS_CS) 6715084Sjohnlev return (0 | SEL_UPL); 6725084Sjohnlev else 6735084Sjohnlev return (0); 6745084Sjohnlev } 6755084Sjohnlev 6760Sstevel@tonic-gate #elif defined(__i386) 6770Sstevel@tonic-gate return (sr | SEL_TI_LDT | SEL_UPL); 6780Sstevel@tonic-gate #endif 6790Sstevel@tonic-gate } 6800Sstevel@tonic-gate 6810Sstevel@tonic-gate /* 6820Sstevel@tonic-gate * Set general registers. 6830Sstevel@tonic-gate */ 6840Sstevel@tonic-gate void 6850Sstevel@tonic-gate setgregs(klwp_t *lwp, gregset_t grp) 6860Sstevel@tonic-gate { 6870Sstevel@tonic-gate struct regs *rp = lwptoregs(lwp); 6880Sstevel@tonic-gate model_t datamodel = lwp_getdatamodel(lwp); 6890Sstevel@tonic-gate 6900Sstevel@tonic-gate #if defined(__amd64) 6910Sstevel@tonic-gate struct pcb *pcb = &lwp->lwp_pcb; 6920Sstevel@tonic-gate int thisthread = lwptot(lwp) == curthread; 6930Sstevel@tonic-gate 6940Sstevel@tonic-gate if (datamodel == DATAMODEL_NATIVE) { 6950Sstevel@tonic-gate 6960Sstevel@tonic-gate if (thisthread) 6970Sstevel@tonic-gate (void) save_syscall_args(); /* copy the args */ 6980Sstevel@tonic-gate 6990Sstevel@tonic-gate rp->r_rdi = grp[REG_RDI]; 7000Sstevel@tonic-gate rp->r_rsi = grp[REG_RSI]; 7010Sstevel@tonic-gate rp->r_rdx = grp[REG_RDX]; 7020Sstevel@tonic-gate rp->r_rcx = grp[REG_RCX]; 7030Sstevel@tonic-gate rp->r_r8 = grp[REG_R8]; 7040Sstevel@tonic-gate rp->r_r9 = grp[REG_R9]; 7050Sstevel@tonic-gate rp->r_rax = grp[REG_RAX]; 7060Sstevel@tonic-gate rp->r_rbx = grp[REG_RBX]; 7070Sstevel@tonic-gate rp->r_rbp = grp[REG_RBP]; 7080Sstevel@tonic-gate rp->r_r10 = grp[REG_R10]; 7090Sstevel@tonic-gate rp->r_r11 = grp[REG_R11]; 7100Sstevel@tonic-gate rp->r_r12 = grp[REG_R12]; 7110Sstevel@tonic-gate rp->r_r13 = grp[REG_R13]; 7120Sstevel@tonic-gate rp->r_r14 = grp[REG_R14]; 7130Sstevel@tonic-gate rp->r_r15 = grp[REG_R15]; 7140Sstevel@tonic-gate rp->r_trapno = grp[REG_TRAPNO]; 7150Sstevel@tonic-gate rp->r_err = grp[REG_ERR]; 7160Sstevel@tonic-gate rp->r_rip = grp[REG_RIP]; 7170Sstevel@tonic-gate /* 7180Sstevel@tonic-gate * Setting %cs or %ss to anything else is quietly but 7190Sstevel@tonic-gate * quite definitely forbidden! 7200Sstevel@tonic-gate */ 7210Sstevel@tonic-gate rp->r_cs = UCS_SEL; 7220Sstevel@tonic-gate rp->r_ss = UDS_SEL; 7230Sstevel@tonic-gate rp->r_rsp = grp[REG_RSP]; 7240Sstevel@tonic-gate 7250Sstevel@tonic-gate if (thisthread) 7260Sstevel@tonic-gate kpreempt_disable(); 7270Sstevel@tonic-gate 7280Sstevel@tonic-gate pcb->pcb_ds = UDS_SEL; 7290Sstevel@tonic-gate pcb->pcb_es = UDS_SEL; 7300Sstevel@tonic-gate 7310Sstevel@tonic-gate /* 7320Sstevel@tonic-gate * 64-bit processes -are- allowed to set their fsbase/gsbase 7330Sstevel@tonic-gate * values directly, but only if they're using the segment 7340Sstevel@tonic-gate * selectors that allow that semantic. 7350Sstevel@tonic-gate * 7360Sstevel@tonic-gate * (32-bit processes must use lwp_set_private().) 7370Sstevel@tonic-gate */ 7380Sstevel@tonic-gate pcb->pcb_fsbase = grp[REG_FSBASE]; 7390Sstevel@tonic-gate pcb->pcb_gsbase = grp[REG_GSBASE]; 7405084Sjohnlev pcb->pcb_fs = fix_segreg(grp[REG_FS], IS_NOT_CS, datamodel); 7415084Sjohnlev pcb->pcb_gs = fix_segreg(grp[REG_GS], IS_NOT_CS, datamodel); 7420Sstevel@tonic-gate 7430Sstevel@tonic-gate /* 7440Sstevel@tonic-gate * Ensure that we go out via update_sregs 7450Sstevel@tonic-gate */ 7464503Ssudheer pcb->pcb_rupdate = 1; 7470Sstevel@tonic-gate lwptot(lwp)->t_post_sys = 1; 7480Sstevel@tonic-gate if (thisthread) 7490Sstevel@tonic-gate kpreempt_enable(); 7500Sstevel@tonic-gate #if defined(_SYSCALL32_IMPL) 7510Sstevel@tonic-gate } else { 7520Sstevel@tonic-gate rp->r_rdi = (uint32_t)grp[REG_RDI]; 7530Sstevel@tonic-gate rp->r_rsi = (uint32_t)grp[REG_RSI]; 7540Sstevel@tonic-gate rp->r_rdx = (uint32_t)grp[REG_RDX]; 7550Sstevel@tonic-gate rp->r_rcx = (uint32_t)grp[REG_RCX]; 7560Sstevel@tonic-gate rp->r_rax = (uint32_t)grp[REG_RAX]; 7570Sstevel@tonic-gate rp->r_rbx = (uint32_t)grp[REG_RBX]; 7580Sstevel@tonic-gate rp->r_rbp = (uint32_t)grp[REG_RBP]; 7590Sstevel@tonic-gate rp->r_trapno = (uint32_t)grp[REG_TRAPNO]; 7600Sstevel@tonic-gate rp->r_err = (uint32_t)grp[REG_ERR]; 7610Sstevel@tonic-gate rp->r_rip = (uint32_t)grp[REG_RIP]; 7620Sstevel@tonic-gate 7635084Sjohnlev rp->r_cs = fix_segreg(grp[REG_CS], IS_CS, datamodel); 7645084Sjohnlev rp->r_ss = fix_segreg(grp[REG_DS], IS_NOT_CS, datamodel); 7650Sstevel@tonic-gate 7660Sstevel@tonic-gate rp->r_rsp = (uint32_t)grp[REG_RSP]; 7670Sstevel@tonic-gate 7680Sstevel@tonic-gate if (thisthread) 7690Sstevel@tonic-gate kpreempt_disable(); 7700Sstevel@tonic-gate 7715084Sjohnlev pcb->pcb_ds = fix_segreg(grp[REG_DS], IS_NOT_CS, datamodel); 7725084Sjohnlev pcb->pcb_es = fix_segreg(grp[REG_ES], IS_NOT_CS, datamodel); 7730Sstevel@tonic-gate 7740Sstevel@tonic-gate /* 7750Sstevel@tonic-gate * (See fsbase/gsbase commentary above) 7760Sstevel@tonic-gate */ 7775084Sjohnlev pcb->pcb_fs = fix_segreg(grp[REG_FS], IS_NOT_CS, datamodel); 7785084Sjohnlev pcb->pcb_gs = fix_segreg(grp[REG_GS], IS_NOT_CS, datamodel); 7790Sstevel@tonic-gate 7800Sstevel@tonic-gate /* 7810Sstevel@tonic-gate * Ensure that we go out via update_sregs 7820Sstevel@tonic-gate */ 7834503Ssudheer pcb->pcb_rupdate = 1; 7840Sstevel@tonic-gate lwptot(lwp)->t_post_sys = 1; 7850Sstevel@tonic-gate if (thisthread) 7860Sstevel@tonic-gate kpreempt_enable(); 7870Sstevel@tonic-gate #endif 7880Sstevel@tonic-gate } 7890Sstevel@tonic-gate 7900Sstevel@tonic-gate /* 7910Sstevel@tonic-gate * Only certain bits of the flags register can be modified. 7920Sstevel@tonic-gate */ 7930Sstevel@tonic-gate rp->r_rfl = (rp->r_rfl & ~PSL_USERMASK) | 7940Sstevel@tonic-gate (grp[REG_RFL] & PSL_USERMASK); 7950Sstevel@tonic-gate 7960Sstevel@tonic-gate #elif defined(__i386) 7970Sstevel@tonic-gate 7980Sstevel@tonic-gate /* 7990Sstevel@tonic-gate * Only certain bits of the flags register can be modified. 8000Sstevel@tonic-gate */ 8010Sstevel@tonic-gate grp[EFL] = (rp->r_efl & ~PSL_USERMASK) | (grp[EFL] & PSL_USERMASK); 8020Sstevel@tonic-gate 8030Sstevel@tonic-gate /* 8040Sstevel@tonic-gate * Copy saved registers from user stack. 8050Sstevel@tonic-gate */ 8060Sstevel@tonic-gate bcopy(grp, &rp->r_gs, sizeof (gregset_t)); 8070Sstevel@tonic-gate 8085084Sjohnlev rp->r_cs = fix_segreg(rp->r_cs, IS_CS, datamodel); 8095084Sjohnlev rp->r_ss = fix_segreg(rp->r_ss, IS_NOT_CS, datamodel); 8105084Sjohnlev rp->r_ds = fix_segreg(rp->r_ds, IS_NOT_CS, datamodel); 8115084Sjohnlev rp->r_es = fix_segreg(rp->r_es, IS_NOT_CS, datamodel); 8125084Sjohnlev rp->r_fs = fix_segreg(rp->r_fs, IS_NOT_CS, datamodel); 8135084Sjohnlev rp->r_gs = fix_segreg(rp->r_gs, IS_NOT_CS, datamodel); 8140Sstevel@tonic-gate 8150Sstevel@tonic-gate #endif /* __i386 */ 8160Sstevel@tonic-gate } 8170Sstevel@tonic-gate 8180Sstevel@tonic-gate /* 8190Sstevel@tonic-gate * Determine whether eip is likely to have an interrupt frame 8200Sstevel@tonic-gate * on the stack. We do this by comparing the address to the 8210Sstevel@tonic-gate * range of addresses spanned by several well-known routines. 8220Sstevel@tonic-gate */ 8230Sstevel@tonic-gate extern void _interrupt(); 8240Sstevel@tonic-gate extern void _allsyscalls(); 8250Sstevel@tonic-gate extern void _cmntrap(); 8260Sstevel@tonic-gate extern void fakesoftint(); 8270Sstevel@tonic-gate 8280Sstevel@tonic-gate extern size_t _interrupt_size; 8290Sstevel@tonic-gate extern size_t _allsyscalls_size; 8300Sstevel@tonic-gate extern size_t _cmntrap_size; 8310Sstevel@tonic-gate extern size_t _fakesoftint_size; 8320Sstevel@tonic-gate 8330Sstevel@tonic-gate /* 8340Sstevel@tonic-gate * Get a pc-only stacktrace. Used for kmem_alloc() buffer ownership tracking. 8350Sstevel@tonic-gate * Returns MIN(current stack depth, pcstack_limit). 8360Sstevel@tonic-gate */ 8370Sstevel@tonic-gate int 8380Sstevel@tonic-gate getpcstack(pc_t *pcstack, int pcstack_limit) 8390Sstevel@tonic-gate { 8400Sstevel@tonic-gate struct frame *fp = (struct frame *)getfp(); 8410Sstevel@tonic-gate struct frame *nextfp, *minfp, *stacktop; 8420Sstevel@tonic-gate int depth = 0; 8430Sstevel@tonic-gate int on_intr; 8440Sstevel@tonic-gate uintptr_t pc; 8450Sstevel@tonic-gate 8460Sstevel@tonic-gate if ((on_intr = CPU_ON_INTR(CPU)) != 0) 8470Sstevel@tonic-gate stacktop = (struct frame *)(CPU->cpu_intr_stack + SA(MINFRAME)); 8480Sstevel@tonic-gate else 8490Sstevel@tonic-gate stacktop = (struct frame *)curthread->t_stk; 8500Sstevel@tonic-gate minfp = fp; 8510Sstevel@tonic-gate 8520Sstevel@tonic-gate pc = ((struct regs *)fp)->r_pc; 8530Sstevel@tonic-gate 8540Sstevel@tonic-gate while (depth < pcstack_limit) { 8550Sstevel@tonic-gate nextfp = (struct frame *)fp->fr_savfp; 8560Sstevel@tonic-gate pc = fp->fr_savpc; 8570Sstevel@tonic-gate if (nextfp <= minfp || nextfp >= stacktop) { 8580Sstevel@tonic-gate if (on_intr) { 8590Sstevel@tonic-gate /* 8600Sstevel@tonic-gate * Hop from interrupt stack to thread stack. 8610Sstevel@tonic-gate */ 8620Sstevel@tonic-gate stacktop = (struct frame *)curthread->t_stk; 8630Sstevel@tonic-gate minfp = (struct frame *)curthread->t_stkbase; 8640Sstevel@tonic-gate on_intr = 0; 8650Sstevel@tonic-gate continue; 8660Sstevel@tonic-gate } 8670Sstevel@tonic-gate break; 8680Sstevel@tonic-gate } 8690Sstevel@tonic-gate pcstack[depth++] = (pc_t)pc; 8700Sstevel@tonic-gate fp = nextfp; 8710Sstevel@tonic-gate minfp = fp; 8720Sstevel@tonic-gate } 8730Sstevel@tonic-gate return (depth); 8740Sstevel@tonic-gate } 8750Sstevel@tonic-gate 8760Sstevel@tonic-gate /* 8770Sstevel@tonic-gate * The following ELF header fields are defined as processor-specific 8780Sstevel@tonic-gate * in the V8 ABI: 8790Sstevel@tonic-gate * 8800Sstevel@tonic-gate * e_ident[EI_DATA] encoding of the processor-specific 8810Sstevel@tonic-gate * data in the object file 8820Sstevel@tonic-gate * e_machine processor identification 8830Sstevel@tonic-gate * e_flags processor-specific flags associated 8840Sstevel@tonic-gate * with the file 8850Sstevel@tonic-gate */ 8860Sstevel@tonic-gate 8870Sstevel@tonic-gate /* 8880Sstevel@tonic-gate * The value of at_flags reflects a platform's cpu module support. 8890Sstevel@tonic-gate * at_flags is used to check for allowing a binary to execute and 8900Sstevel@tonic-gate * is passed as the value of the AT_FLAGS auxiliary vector. 8910Sstevel@tonic-gate */ 8920Sstevel@tonic-gate int at_flags = 0; 8930Sstevel@tonic-gate 8940Sstevel@tonic-gate /* 8950Sstevel@tonic-gate * Check the processor-specific fields of an ELF header. 8960Sstevel@tonic-gate * 8970Sstevel@tonic-gate * returns 1 if the fields are valid, 0 otherwise 8980Sstevel@tonic-gate */ 8990Sstevel@tonic-gate /*ARGSUSED2*/ 9000Sstevel@tonic-gate int 9010Sstevel@tonic-gate elfheadcheck( 9020Sstevel@tonic-gate unsigned char e_data, 9030Sstevel@tonic-gate Elf32_Half e_machine, 9040Sstevel@tonic-gate Elf32_Word e_flags) 9050Sstevel@tonic-gate { 9060Sstevel@tonic-gate if (e_data != ELFDATA2LSB) 9070Sstevel@tonic-gate return (0); 9080Sstevel@tonic-gate #if defined(__amd64) 9090Sstevel@tonic-gate if (e_machine == EM_AMD64) 9100Sstevel@tonic-gate return (1); 9110Sstevel@tonic-gate #endif 9120Sstevel@tonic-gate return (e_machine == EM_386); 9130Sstevel@tonic-gate } 9140Sstevel@tonic-gate 9150Sstevel@tonic-gate uint_t auxv_hwcap_include = 0; /* patch to enable unrecognized features */ 9160Sstevel@tonic-gate uint_t auxv_hwcap_exclude = 0; /* patch for broken cpus, debugging */ 9170Sstevel@tonic-gate #if defined(_SYSCALL32_IMPL) 9180Sstevel@tonic-gate uint_t auxv_hwcap32_include = 0; /* ditto for 32-bit apps */ 9190Sstevel@tonic-gate uint_t auxv_hwcap32_exclude = 0; /* ditto for 32-bit apps */ 9200Sstevel@tonic-gate #endif 9210Sstevel@tonic-gate 9220Sstevel@tonic-gate /* 9230Sstevel@tonic-gate * Gather information about the processor and place it into auxv_hwcap 9240Sstevel@tonic-gate * so that it can be exported to the linker via the aux vector. 9250Sstevel@tonic-gate * 9260Sstevel@tonic-gate * We use this seemingly complicated mechanism so that we can ensure 9270Sstevel@tonic-gate * that /etc/system can be used to override what the system can or 9280Sstevel@tonic-gate * cannot discover for itself. 9290Sstevel@tonic-gate */ 9300Sstevel@tonic-gate void 9310Sstevel@tonic-gate bind_hwcap(void) 9320Sstevel@tonic-gate { 9330Sstevel@tonic-gate uint_t cpu_hwcap_flags = cpuid_pass4(NULL); 9340Sstevel@tonic-gate 9350Sstevel@tonic-gate auxv_hwcap = (auxv_hwcap_include | cpu_hwcap_flags) & 9360Sstevel@tonic-gate ~auxv_hwcap_exclude; 9370Sstevel@tonic-gate 9380Sstevel@tonic-gate #if defined(__amd64) 9390Sstevel@tonic-gate /* 9400Sstevel@tonic-gate * On AMD processors, sysenter just doesn't work at all 9410Sstevel@tonic-gate * when the kernel is in long mode. On IA-32e processors 9420Sstevel@tonic-gate * it does, but there's no real point in all the alternate 9430Sstevel@tonic-gate * mechanism when syscall works on both. 9440Sstevel@tonic-gate * 9450Sstevel@tonic-gate * Besides, the kernel's sysenter handler is expecting a 9460Sstevel@tonic-gate * 32-bit lwp ... 9470Sstevel@tonic-gate */ 9480Sstevel@tonic-gate auxv_hwcap &= ~AV_386_SEP; 9493446Smrj #else 9503446Smrj /* 9513446Smrj * 32-bit processes can -always- use the lahf/sahf instructions 9523446Smrj */ 9533446Smrj auxv_hwcap |= AV_386_AHF; 9540Sstevel@tonic-gate #endif 9550Sstevel@tonic-gate 9560Sstevel@tonic-gate if (auxv_hwcap_include || auxv_hwcap_exclude) 9570Sstevel@tonic-gate cmn_err(CE_CONT, "?user ABI extensions: %b\n", 9580Sstevel@tonic-gate auxv_hwcap, FMT_AV_386); 9590Sstevel@tonic-gate 9600Sstevel@tonic-gate #if defined(_SYSCALL32_IMPL) 9610Sstevel@tonic-gate auxv_hwcap32 = (auxv_hwcap32_include | cpu_hwcap_flags) & 9624551Ssudheer ~auxv_hwcap32_exclude; 9630Sstevel@tonic-gate 9640Sstevel@tonic-gate #if defined(__amd64) 9650Sstevel@tonic-gate /* 9660Sstevel@tonic-gate * If this is an amd64 architecture machine from Intel, then 9670Sstevel@tonic-gate * syscall -doesn't- work in compatibility mode, only sysenter does. 9680Sstevel@tonic-gate * 9690Sstevel@tonic-gate * Sigh. 9700Sstevel@tonic-gate */ 9710Sstevel@tonic-gate if (!cpuid_syscall32_insn(NULL)) 9720Sstevel@tonic-gate auxv_hwcap32 &= ~AV_386_AMD_SYSC; 9733446Smrj 9743446Smrj /* 9753446Smrj * 32-bit processes can -always- use the lahf/sahf instructions 9763446Smrj */ 9773446Smrj auxv_hwcap32 |= AV_386_AHF; 9780Sstevel@tonic-gate #endif 9790Sstevel@tonic-gate 9800Sstevel@tonic-gate if (auxv_hwcap32_include || auxv_hwcap32_exclude) 9810Sstevel@tonic-gate cmn_err(CE_CONT, "?32-bit user ABI extensions: %b\n", 9820Sstevel@tonic-gate auxv_hwcap32, FMT_AV_386); 9830Sstevel@tonic-gate #endif 9840Sstevel@tonic-gate } 9850Sstevel@tonic-gate 9860Sstevel@tonic-gate /* 9870Sstevel@tonic-gate * sync_icache() - this is called 9880Sstevel@tonic-gate * in proc/fs/prusrio.c. x86 has an unified cache and therefore 9890Sstevel@tonic-gate * this is a nop. 9900Sstevel@tonic-gate */ 9910Sstevel@tonic-gate /* ARGSUSED */ 9920Sstevel@tonic-gate void 9930Sstevel@tonic-gate sync_icache(caddr_t addr, uint_t len) 9940Sstevel@tonic-gate { 9950Sstevel@tonic-gate /* Do nothing for now */ 9960Sstevel@tonic-gate } 9970Sstevel@tonic-gate 9980Sstevel@tonic-gate /*ARGSUSED*/ 9990Sstevel@tonic-gate void 10000Sstevel@tonic-gate sync_data_memory(caddr_t va, size_t len) 10010Sstevel@tonic-gate { 10020Sstevel@tonic-gate /* Not implemented for this platform */ 10030Sstevel@tonic-gate } 10040Sstevel@tonic-gate 10050Sstevel@tonic-gate int 10060Sstevel@tonic-gate __ipltospl(int ipl) 10070Sstevel@tonic-gate { 10080Sstevel@tonic-gate return (ipltospl(ipl)); 10090Sstevel@tonic-gate } 10100Sstevel@tonic-gate 10110Sstevel@tonic-gate /* 10120Sstevel@tonic-gate * The panic code invokes panic_saveregs() to record the contents of a 10130Sstevel@tonic-gate * regs structure into the specified panic_data structure for debuggers. 10140Sstevel@tonic-gate */ 10150Sstevel@tonic-gate void 10160Sstevel@tonic-gate panic_saveregs(panic_data_t *pdp, struct regs *rp) 10170Sstevel@tonic-gate { 10180Sstevel@tonic-gate panic_nv_t *pnv = PANICNVGET(pdp); 10190Sstevel@tonic-gate 10200Sstevel@tonic-gate struct cregs creg; 10210Sstevel@tonic-gate 10220Sstevel@tonic-gate getcregs(&creg); 10230Sstevel@tonic-gate 10240Sstevel@tonic-gate #if defined(__amd64) 10250Sstevel@tonic-gate PANICNVADD(pnv, "rdi", rp->r_rdi); 10260Sstevel@tonic-gate PANICNVADD(pnv, "rsi", rp->r_rsi); 10270Sstevel@tonic-gate PANICNVADD(pnv, "rdx", rp->r_rdx); 10280Sstevel@tonic-gate PANICNVADD(pnv, "rcx", rp->r_rcx); 10290Sstevel@tonic-gate PANICNVADD(pnv, "r8", rp->r_r8); 10300Sstevel@tonic-gate PANICNVADD(pnv, "r9", rp->r_r9); 10310Sstevel@tonic-gate PANICNVADD(pnv, "rax", rp->r_rax); 10320Sstevel@tonic-gate PANICNVADD(pnv, "rbx", rp->r_rbx); 10330Sstevel@tonic-gate PANICNVADD(pnv, "rbp", rp->r_rbp); 10340Sstevel@tonic-gate PANICNVADD(pnv, "r10", rp->r_r10); 10350Sstevel@tonic-gate PANICNVADD(pnv, "r10", rp->r_r10); 10360Sstevel@tonic-gate PANICNVADD(pnv, "r11", rp->r_r11); 10370Sstevel@tonic-gate PANICNVADD(pnv, "r12", rp->r_r12); 10380Sstevel@tonic-gate PANICNVADD(pnv, "r13", rp->r_r13); 10390Sstevel@tonic-gate PANICNVADD(pnv, "r14", rp->r_r14); 10400Sstevel@tonic-gate PANICNVADD(pnv, "r15", rp->r_r15); 10413446Smrj PANICNVADD(pnv, "fsbase", rdmsr(MSR_AMD_FSBASE)); 10423446Smrj PANICNVADD(pnv, "gsbase", rdmsr(MSR_AMD_GSBASE)); 10430Sstevel@tonic-gate PANICNVADD(pnv, "ds", rp->r_ds); 10440Sstevel@tonic-gate PANICNVADD(pnv, "es", rp->r_es); 10450Sstevel@tonic-gate PANICNVADD(pnv, "fs", rp->r_fs); 10460Sstevel@tonic-gate PANICNVADD(pnv, "gs", rp->r_gs); 10470Sstevel@tonic-gate PANICNVADD(pnv, "trapno", rp->r_trapno); 10480Sstevel@tonic-gate PANICNVADD(pnv, "err", rp->r_err); 10490Sstevel@tonic-gate PANICNVADD(pnv, "rip", rp->r_rip); 10500Sstevel@tonic-gate PANICNVADD(pnv, "cs", rp->r_cs); 10510Sstevel@tonic-gate PANICNVADD(pnv, "rflags", rp->r_rfl); 10520Sstevel@tonic-gate PANICNVADD(pnv, "rsp", rp->r_rsp); 10530Sstevel@tonic-gate PANICNVADD(pnv, "ss", rp->r_ss); 10540Sstevel@tonic-gate PANICNVADD(pnv, "gdt_hi", (uint64_t)(creg.cr_gdt._l[3])); 10550Sstevel@tonic-gate PANICNVADD(pnv, "gdt_lo", (uint64_t)(creg.cr_gdt._l[0])); 10560Sstevel@tonic-gate PANICNVADD(pnv, "idt_hi", (uint64_t)(creg.cr_idt._l[3])); 10570Sstevel@tonic-gate PANICNVADD(pnv, "idt_lo", (uint64_t)(creg.cr_idt._l[0])); 10580Sstevel@tonic-gate #elif defined(__i386) 10590Sstevel@tonic-gate PANICNVADD(pnv, "gs", (uint32_t)rp->r_gs); 10600Sstevel@tonic-gate PANICNVADD(pnv, "fs", (uint32_t)rp->r_fs); 10610Sstevel@tonic-gate PANICNVADD(pnv, "es", (uint32_t)rp->r_es); 10620Sstevel@tonic-gate PANICNVADD(pnv, "ds", (uint32_t)rp->r_ds); 10630Sstevel@tonic-gate PANICNVADD(pnv, "edi", (uint32_t)rp->r_edi); 10640Sstevel@tonic-gate PANICNVADD(pnv, "esi", (uint32_t)rp->r_esi); 10650Sstevel@tonic-gate PANICNVADD(pnv, "ebp", (uint32_t)rp->r_ebp); 10660Sstevel@tonic-gate PANICNVADD(pnv, "esp", (uint32_t)rp->r_esp); 10670Sstevel@tonic-gate PANICNVADD(pnv, "ebx", (uint32_t)rp->r_ebx); 10680Sstevel@tonic-gate PANICNVADD(pnv, "edx", (uint32_t)rp->r_edx); 10690Sstevel@tonic-gate PANICNVADD(pnv, "ecx", (uint32_t)rp->r_ecx); 10700Sstevel@tonic-gate PANICNVADD(pnv, "eax", (uint32_t)rp->r_eax); 10710Sstevel@tonic-gate PANICNVADD(pnv, "trapno", (uint32_t)rp->r_trapno); 10720Sstevel@tonic-gate PANICNVADD(pnv, "err", (uint32_t)rp->r_err); 10730Sstevel@tonic-gate PANICNVADD(pnv, "eip", (uint32_t)rp->r_eip); 10740Sstevel@tonic-gate PANICNVADD(pnv, "cs", (uint32_t)rp->r_cs); 10750Sstevel@tonic-gate PANICNVADD(pnv, "eflags", (uint32_t)rp->r_efl); 10760Sstevel@tonic-gate PANICNVADD(pnv, "uesp", (uint32_t)rp->r_uesp); 10770Sstevel@tonic-gate PANICNVADD(pnv, "ss", (uint32_t)rp->r_ss); 10780Sstevel@tonic-gate PANICNVADD(pnv, "gdt", creg.cr_gdt); 10790Sstevel@tonic-gate PANICNVADD(pnv, "idt", creg.cr_idt); 10800Sstevel@tonic-gate #endif /* __i386 */ 10810Sstevel@tonic-gate 10820Sstevel@tonic-gate PANICNVADD(pnv, "ldt", creg.cr_ldt); 10830Sstevel@tonic-gate PANICNVADD(pnv, "task", creg.cr_task); 10840Sstevel@tonic-gate PANICNVADD(pnv, "cr0", creg.cr_cr0); 10850Sstevel@tonic-gate PANICNVADD(pnv, "cr2", creg.cr_cr2); 10860Sstevel@tonic-gate PANICNVADD(pnv, "cr3", creg.cr_cr3); 10870Sstevel@tonic-gate if (creg.cr_cr4) 10880Sstevel@tonic-gate PANICNVADD(pnv, "cr4", creg.cr_cr4); 10890Sstevel@tonic-gate 10900Sstevel@tonic-gate PANICNVSET(pdp, pnv); 10910Sstevel@tonic-gate } 10920Sstevel@tonic-gate 10930Sstevel@tonic-gate #define TR_ARG_MAX 6 /* Max args to print, same as SPARC */ 10940Sstevel@tonic-gate 10950Sstevel@tonic-gate #if !defined(__amd64) 10960Sstevel@tonic-gate 10970Sstevel@tonic-gate /* 10980Sstevel@tonic-gate * Given a return address (%eip), determine the likely number of arguments 10990Sstevel@tonic-gate * that were pushed on the stack prior to its execution. We do this by 11000Sstevel@tonic-gate * expecting that a typical call sequence consists of pushing arguments on 11010Sstevel@tonic-gate * the stack, executing a call instruction, and then performing an add 11020Sstevel@tonic-gate * on %esp to restore it to the value prior to pushing the arguments for 11030Sstevel@tonic-gate * the call. We attempt to detect such an add, and divide the addend 11040Sstevel@tonic-gate * by the size of a word to determine the number of pushed arguments. 11050Sstevel@tonic-gate * 11060Sstevel@tonic-gate * If we do not find such an add, we punt and return TR_ARG_MAX. It is not 11070Sstevel@tonic-gate * possible to reliably determine if a function took no arguments (i.e. was 11080Sstevel@tonic-gate * void) because assembler routines do not reliably perform an add on %esp 11090Sstevel@tonic-gate * immediately upon returning (eg. _sys_call()), so returning TR_ARG_MAX is 11100Sstevel@tonic-gate * safer than returning 0. 11110Sstevel@tonic-gate */ 11120Sstevel@tonic-gate static ulong_t 11130Sstevel@tonic-gate argcount(uintptr_t eip) 11140Sstevel@tonic-gate { 11150Sstevel@tonic-gate const uint8_t *ins = (const uint8_t *)eip; 11160Sstevel@tonic-gate ulong_t n; 11170Sstevel@tonic-gate 11180Sstevel@tonic-gate enum { 11190Sstevel@tonic-gate M_MODRM_ESP = 0xc4, /* Mod/RM byte indicates %esp */ 11200Sstevel@tonic-gate M_ADD_IMM32 = 0x81, /* ADD imm32 to r/m32 */ 11210Sstevel@tonic-gate M_ADD_IMM8 = 0x83 /* ADD imm8 to r/m32 */ 11220Sstevel@tonic-gate }; 11230Sstevel@tonic-gate 11240Sstevel@tonic-gate if (eip < KERNELBASE || ins[1] != M_MODRM_ESP) 11250Sstevel@tonic-gate return (TR_ARG_MAX); 11260Sstevel@tonic-gate 11270Sstevel@tonic-gate switch (ins[0]) { 11280Sstevel@tonic-gate case M_ADD_IMM32: 11290Sstevel@tonic-gate n = ins[2] + (ins[3] << 8) + (ins[4] << 16) + (ins[5] << 24); 11300Sstevel@tonic-gate break; 11310Sstevel@tonic-gate 11320Sstevel@tonic-gate case M_ADD_IMM8: 11330Sstevel@tonic-gate n = ins[2]; 11340Sstevel@tonic-gate break; 11350Sstevel@tonic-gate 11360Sstevel@tonic-gate default: 11370Sstevel@tonic-gate return (TR_ARG_MAX); 11380Sstevel@tonic-gate } 11390Sstevel@tonic-gate 11400Sstevel@tonic-gate n /= sizeof (long); 11410Sstevel@tonic-gate return (MIN(n, TR_ARG_MAX)); 11420Sstevel@tonic-gate } 11430Sstevel@tonic-gate 11440Sstevel@tonic-gate #endif /* !__amd64 */ 11450Sstevel@tonic-gate 11460Sstevel@tonic-gate /* 11470Sstevel@tonic-gate * Print a stack backtrace using the specified frame pointer. We delay two 11480Sstevel@tonic-gate * seconds before continuing, unless this is the panic traceback. Note 11490Sstevel@tonic-gate * that the frame for the starting stack pointer value is omitted because 11500Sstevel@tonic-gate * the corresponding %eip is not known. 11510Sstevel@tonic-gate */ 11520Sstevel@tonic-gate #if defined(__amd64) 11530Sstevel@tonic-gate 11540Sstevel@tonic-gate void 11550Sstevel@tonic-gate traceback(caddr_t fpreg) 11560Sstevel@tonic-gate { 11570Sstevel@tonic-gate struct frame *fp = (struct frame *)fpreg; 11580Sstevel@tonic-gate struct frame *nextfp; 11590Sstevel@tonic-gate uintptr_t pc, nextpc; 11600Sstevel@tonic-gate ulong_t off; 11610Sstevel@tonic-gate char args[TR_ARG_MAX * 2 + 16], *sym; 11620Sstevel@tonic-gate 11630Sstevel@tonic-gate if (!panicstr) 11640Sstevel@tonic-gate printf("traceback: %%fp = %p\n", (void *)fp); 11650Sstevel@tonic-gate 11665084Sjohnlev fp = (struct frame *)plat_traceback(fpreg); 11670Sstevel@tonic-gate if ((uintptr_t)fp < KERNELBASE) 11680Sstevel@tonic-gate goto out; 11690Sstevel@tonic-gate 11700Sstevel@tonic-gate pc = fp->fr_savpc; 11710Sstevel@tonic-gate fp = (struct frame *)fp->fr_savfp; 11720Sstevel@tonic-gate 11730Sstevel@tonic-gate while ((uintptr_t)fp >= KERNELBASE) { 11740Sstevel@tonic-gate /* 11750Sstevel@tonic-gate * XX64 Until port is complete tolerate 8-byte aligned 11760Sstevel@tonic-gate * frame pointers but flag with a warning so they can 11770Sstevel@tonic-gate * be fixed. 11780Sstevel@tonic-gate */ 11790Sstevel@tonic-gate if (((uintptr_t)fp & (STACK_ALIGN - 1)) != 0) { 11800Sstevel@tonic-gate if (((uintptr_t)fp & (8 - 1)) == 0) { 11810Sstevel@tonic-gate printf(" >> warning! 8-byte" 11820Sstevel@tonic-gate " aligned %%fp = %p\n", (void *)fp); 11830Sstevel@tonic-gate } else { 11840Sstevel@tonic-gate printf( 11850Sstevel@tonic-gate " >> mis-aligned %%fp = %p\n", (void *)fp); 11860Sstevel@tonic-gate break; 11870Sstevel@tonic-gate } 11880Sstevel@tonic-gate } 11890Sstevel@tonic-gate 11900Sstevel@tonic-gate args[0] = '\0'; 11910Sstevel@tonic-gate nextpc = (uintptr_t)fp->fr_savpc; 11920Sstevel@tonic-gate nextfp = (struct frame *)fp->fr_savfp; 11930Sstevel@tonic-gate if ((sym = kobj_getsymname(pc, &off)) != NULL) { 11940Sstevel@tonic-gate printf("%016lx %s:%s+%lx (%s)\n", (uintptr_t)fp, 11950Sstevel@tonic-gate mod_containing_pc((caddr_t)pc), sym, off, args); 11960Sstevel@tonic-gate } else { 11970Sstevel@tonic-gate printf("%016lx %lx (%s)\n", 11980Sstevel@tonic-gate (uintptr_t)fp, pc, args); 11990Sstevel@tonic-gate } 12000Sstevel@tonic-gate 12010Sstevel@tonic-gate pc = nextpc; 12020Sstevel@tonic-gate fp = nextfp; 12030Sstevel@tonic-gate } 12040Sstevel@tonic-gate out: 12050Sstevel@tonic-gate if (!panicstr) { 12060Sstevel@tonic-gate printf("end of traceback\n"); 12070Sstevel@tonic-gate DELAY(2 * MICROSEC); 12080Sstevel@tonic-gate } 12090Sstevel@tonic-gate } 12100Sstevel@tonic-gate 12110Sstevel@tonic-gate #elif defined(__i386) 12120Sstevel@tonic-gate 12130Sstevel@tonic-gate void 12140Sstevel@tonic-gate traceback(caddr_t fpreg) 12150Sstevel@tonic-gate { 12160Sstevel@tonic-gate struct frame *fp = (struct frame *)fpreg; 12170Sstevel@tonic-gate struct frame *nextfp, *minfp, *stacktop; 12180Sstevel@tonic-gate uintptr_t pc, nextpc; 12190Sstevel@tonic-gate 12200Sstevel@tonic-gate cpu_t *cpu; 12210Sstevel@tonic-gate 12220Sstevel@tonic-gate /* 12230Sstevel@tonic-gate * args[] holds TR_ARG_MAX hex long args, plus ", " or '\0'. 12240Sstevel@tonic-gate */ 12250Sstevel@tonic-gate char args[TR_ARG_MAX * 2 + 8], *p; 12260Sstevel@tonic-gate 12270Sstevel@tonic-gate int on_intr; 12280Sstevel@tonic-gate ulong_t off; 12290Sstevel@tonic-gate char *sym; 12300Sstevel@tonic-gate 12310Sstevel@tonic-gate if (!panicstr) 12320Sstevel@tonic-gate printf("traceback: %%fp = %p\n", (void *)fp); 12330Sstevel@tonic-gate 12340Sstevel@tonic-gate /* 12350Sstevel@tonic-gate * If we are panicking, all high-level interrupt information in 12360Sstevel@tonic-gate * CPU was overwritten. panic_cpu has the correct values. 12370Sstevel@tonic-gate */ 12380Sstevel@tonic-gate kpreempt_disable(); /* prevent migration */ 12390Sstevel@tonic-gate 12400Sstevel@tonic-gate cpu = (panicstr && CPU->cpu_id == panic_cpu.cpu_id)? &panic_cpu : CPU; 12410Sstevel@tonic-gate 12420Sstevel@tonic-gate if ((on_intr = CPU_ON_INTR(cpu)) != 0) 12430Sstevel@tonic-gate stacktop = (struct frame *)(cpu->cpu_intr_stack + SA(MINFRAME)); 12440Sstevel@tonic-gate else 12450Sstevel@tonic-gate stacktop = (struct frame *)curthread->t_stk; 12460Sstevel@tonic-gate 12470Sstevel@tonic-gate kpreempt_enable(); 12480Sstevel@tonic-gate 12495084Sjohnlev fp = (struct frame *)plat_traceback(fpreg); 12500Sstevel@tonic-gate if ((uintptr_t)fp < KERNELBASE) 12510Sstevel@tonic-gate goto out; 12520Sstevel@tonic-gate 12530Sstevel@tonic-gate minfp = fp; /* Baseline minimum frame pointer */ 12540Sstevel@tonic-gate pc = fp->fr_savpc; 12550Sstevel@tonic-gate fp = (struct frame *)fp->fr_savfp; 12560Sstevel@tonic-gate 12570Sstevel@tonic-gate while ((uintptr_t)fp >= KERNELBASE) { 12580Sstevel@tonic-gate ulong_t argc; 12590Sstevel@tonic-gate long *argv; 12600Sstevel@tonic-gate 12610Sstevel@tonic-gate if (fp <= minfp || fp >= stacktop) { 12620Sstevel@tonic-gate if (on_intr) { 12630Sstevel@tonic-gate /* 12640Sstevel@tonic-gate * Hop from interrupt stack to thread stack. 12650Sstevel@tonic-gate */ 12660Sstevel@tonic-gate stacktop = (struct frame *)curthread->t_stk; 12670Sstevel@tonic-gate minfp = (struct frame *)curthread->t_stkbase; 12680Sstevel@tonic-gate on_intr = 0; 12690Sstevel@tonic-gate continue; 12700Sstevel@tonic-gate } 12710Sstevel@tonic-gate break; /* we're outside of the expected range */ 12720Sstevel@tonic-gate } 12730Sstevel@tonic-gate 12740Sstevel@tonic-gate if ((uintptr_t)fp & (STACK_ALIGN - 1)) { 12750Sstevel@tonic-gate printf(" >> mis-aligned %%fp = %p\n", (void *)fp); 12760Sstevel@tonic-gate break; 12770Sstevel@tonic-gate } 12780Sstevel@tonic-gate 12790Sstevel@tonic-gate nextpc = fp->fr_savpc; 12800Sstevel@tonic-gate nextfp = (struct frame *)fp->fr_savfp; 12810Sstevel@tonic-gate argc = argcount(nextpc); 12820Sstevel@tonic-gate argv = (long *)((char *)fp + sizeof (struct frame)); 12830Sstevel@tonic-gate 12840Sstevel@tonic-gate args[0] = '\0'; 12850Sstevel@tonic-gate p = args; 12860Sstevel@tonic-gate while (argc-- > 0 && argv < (long *)stacktop) { 12870Sstevel@tonic-gate p += snprintf(p, args + sizeof (args) - p, 12880Sstevel@tonic-gate "%s%lx", (p == args) ? "" : ", ", *argv++); 12890Sstevel@tonic-gate } 12900Sstevel@tonic-gate 12910Sstevel@tonic-gate if ((sym = kobj_getsymname(pc, &off)) != NULL) { 12920Sstevel@tonic-gate printf("%08lx %s:%s+%lx (%s)\n", (uintptr_t)fp, 12930Sstevel@tonic-gate mod_containing_pc((caddr_t)pc), sym, off, args); 12940Sstevel@tonic-gate } else { 12950Sstevel@tonic-gate printf("%08lx %lx (%s)\n", 12960Sstevel@tonic-gate (uintptr_t)fp, pc, args); 12970Sstevel@tonic-gate } 12980Sstevel@tonic-gate 12990Sstevel@tonic-gate minfp = fp; 13000Sstevel@tonic-gate pc = nextpc; 13010Sstevel@tonic-gate fp = nextfp; 13020Sstevel@tonic-gate } 13030Sstevel@tonic-gate out: 13040Sstevel@tonic-gate if (!panicstr) { 13050Sstevel@tonic-gate printf("end of traceback\n"); 13060Sstevel@tonic-gate DELAY(2 * MICROSEC); 13070Sstevel@tonic-gate } 13080Sstevel@tonic-gate } 13090Sstevel@tonic-gate 13100Sstevel@tonic-gate #endif /* __i386 */ 13110Sstevel@tonic-gate 13120Sstevel@tonic-gate /* 13130Sstevel@tonic-gate * Generate a stack backtrace from a saved register set. 13140Sstevel@tonic-gate */ 13150Sstevel@tonic-gate void 13160Sstevel@tonic-gate traceregs(struct regs *rp) 13170Sstevel@tonic-gate { 13180Sstevel@tonic-gate traceback((caddr_t)rp->r_fp); 13190Sstevel@tonic-gate } 13200Sstevel@tonic-gate 13210Sstevel@tonic-gate void 13220Sstevel@tonic-gate exec_set_sp(size_t stksize) 13230Sstevel@tonic-gate { 13240Sstevel@tonic-gate klwp_t *lwp = ttolwp(curthread); 13250Sstevel@tonic-gate 13260Sstevel@tonic-gate lwptoregs(lwp)->r_sp = (uintptr_t)curproc->p_usrstack - stksize; 13270Sstevel@tonic-gate } 13280Sstevel@tonic-gate 13290Sstevel@tonic-gate hrtime_t 13300Sstevel@tonic-gate gethrtime_waitfree(void) 13310Sstevel@tonic-gate { 13320Sstevel@tonic-gate return (dtrace_gethrtime()); 13330Sstevel@tonic-gate } 13340Sstevel@tonic-gate 13350Sstevel@tonic-gate hrtime_t 13360Sstevel@tonic-gate gethrtime(void) 13370Sstevel@tonic-gate { 13380Sstevel@tonic-gate return (gethrtimef()); 13390Sstevel@tonic-gate } 13400Sstevel@tonic-gate 13410Sstevel@tonic-gate hrtime_t 13420Sstevel@tonic-gate gethrtime_unscaled(void) 13430Sstevel@tonic-gate { 13440Sstevel@tonic-gate return (gethrtimeunscaledf()); 13450Sstevel@tonic-gate } 13460Sstevel@tonic-gate 13470Sstevel@tonic-gate void 13480Sstevel@tonic-gate scalehrtime(hrtime_t *hrt) 13490Sstevel@tonic-gate { 13500Sstevel@tonic-gate scalehrtimef(hrt); 13510Sstevel@tonic-gate } 13520Sstevel@tonic-gate 1353*10797SEric.Saxe@Sun.COM uint64_t 1354*10797SEric.Saxe@Sun.COM unscalehrtime(hrtime_t nsecs) 1355*10797SEric.Saxe@Sun.COM { 1356*10797SEric.Saxe@Sun.COM return (unscalehrtimef(nsecs)); 1357*10797SEric.Saxe@Sun.COM } 1358*10797SEric.Saxe@Sun.COM 13590Sstevel@tonic-gate void 13600Sstevel@tonic-gate gethrestime(timespec_t *tp) 13610Sstevel@tonic-gate { 13620Sstevel@tonic-gate gethrestimef(tp); 13630Sstevel@tonic-gate } 13640Sstevel@tonic-gate 13650Sstevel@tonic-gate #if defined(__amd64) 13660Sstevel@tonic-gate /* 13670Sstevel@tonic-gate * Part of the implementation of hres_tick(); this routine is 13680Sstevel@tonic-gate * easier in C than assembler .. called with the hres_lock held. 13690Sstevel@tonic-gate * 13700Sstevel@tonic-gate * XX64 Many of these timekeeping variables need to be extern'ed in a header 13710Sstevel@tonic-gate */ 13720Sstevel@tonic-gate 13730Sstevel@tonic-gate #include <sys/time.h> 13740Sstevel@tonic-gate #include <sys/machlock.h> 13750Sstevel@tonic-gate 13760Sstevel@tonic-gate extern int one_sec; 13770Sstevel@tonic-gate extern int max_hres_adj; 13780Sstevel@tonic-gate 13790Sstevel@tonic-gate void 13800Sstevel@tonic-gate __adj_hrestime(void) 13810Sstevel@tonic-gate { 13820Sstevel@tonic-gate long long adj; 13830Sstevel@tonic-gate 13840Sstevel@tonic-gate if (hrestime_adj == 0) 13850Sstevel@tonic-gate adj = 0; 13860Sstevel@tonic-gate else if (hrestime_adj > 0) { 13870Sstevel@tonic-gate if (hrestime_adj < max_hres_adj) 13880Sstevel@tonic-gate adj = hrestime_adj; 13890Sstevel@tonic-gate else 13900Sstevel@tonic-gate adj = max_hres_adj; 13910Sstevel@tonic-gate } else { 13920Sstevel@tonic-gate if (hrestime_adj < -max_hres_adj) 13930Sstevel@tonic-gate adj = -max_hres_adj; 13940Sstevel@tonic-gate else 13950Sstevel@tonic-gate adj = hrestime_adj; 13960Sstevel@tonic-gate } 13970Sstevel@tonic-gate 13980Sstevel@tonic-gate timedelta -= adj; 13990Sstevel@tonic-gate hrestime_adj = timedelta; 14000Sstevel@tonic-gate hrestime.tv_nsec += adj; 14010Sstevel@tonic-gate 14020Sstevel@tonic-gate while (hrestime.tv_nsec >= NANOSEC) { 14030Sstevel@tonic-gate one_sec++; 14040Sstevel@tonic-gate hrestime.tv_sec++; 14050Sstevel@tonic-gate hrestime.tv_nsec -= NANOSEC; 14060Sstevel@tonic-gate } 14070Sstevel@tonic-gate } 14080Sstevel@tonic-gate #endif 14090Sstevel@tonic-gate 14100Sstevel@tonic-gate /* 14110Sstevel@tonic-gate * Wrapper functions to maintain backwards compability 14120Sstevel@tonic-gate */ 14130Sstevel@tonic-gate int 14140Sstevel@tonic-gate xcopyin(const void *uaddr, void *kaddr, size_t count) 14150Sstevel@tonic-gate { 14160Sstevel@tonic-gate return (xcopyin_nta(uaddr, kaddr, count, UIO_COPY_CACHED)); 14170Sstevel@tonic-gate } 14180Sstevel@tonic-gate 14190Sstevel@tonic-gate int 14200Sstevel@tonic-gate xcopyout(const void *kaddr, void *uaddr, size_t count) 14210Sstevel@tonic-gate { 14220Sstevel@tonic-gate return (xcopyout_nta(kaddr, uaddr, count, UIO_COPY_CACHED)); 14230Sstevel@tonic-gate } 1424