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
51972Sdv142724 * Common Development and Distribution License (the "License").
61972Sdv142724 * 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 */
212712Snn35248
220Sstevel@tonic-gate /*
239613SAbhinandan.Ekande@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate
280Sstevel@tonic-gate #include <sys/mmu.h>
290Sstevel@tonic-gate #include <sys/systm.h>
300Sstevel@tonic-gate #include <sys/trap.h>
310Sstevel@tonic-gate #include <sys/machtrap.h>
320Sstevel@tonic-gate #include <sys/vtrace.h>
330Sstevel@tonic-gate #include <sys/prsystm.h>
340Sstevel@tonic-gate #include <sys/archsystm.h>
350Sstevel@tonic-gate #include <sys/machsystm.h>
360Sstevel@tonic-gate #include <sys/fpu/fpusystm.h>
370Sstevel@tonic-gate #include <sys/tnf.h>
380Sstevel@tonic-gate #include <sys/tnf_probe.h>
390Sstevel@tonic-gate #include <sys/simulate.h>
400Sstevel@tonic-gate #include <sys/ftrace.h>
410Sstevel@tonic-gate #include <sys/ontrap.h>
420Sstevel@tonic-gate #include <sys/kcpc.h>
430Sstevel@tonic-gate #include <sys/kobj.h>
440Sstevel@tonic-gate #include <sys/procfs.h>
450Sstevel@tonic-gate #include <sys/sun4asi.h>
460Sstevel@tonic-gate #include <sys/sdt.h>
470Sstevel@tonic-gate #include <sys/fpras.h>
489613SAbhinandan.Ekande@Sun.COM #include <sys/contract/process_impl.h>
490Sstevel@tonic-gate
500Sstevel@tonic-gate #ifdef TRAPTRACE
510Sstevel@tonic-gate #include <sys/traptrace.h>
520Sstevel@tonic-gate #endif
530Sstevel@tonic-gate
540Sstevel@tonic-gate int tudebug = 0;
550Sstevel@tonic-gate static int tudebugbpt = 0;
560Sstevel@tonic-gate static int tudebugfpe = 0;
570Sstevel@tonic-gate
580Sstevel@tonic-gate static int alignfaults = 0;
590Sstevel@tonic-gate
600Sstevel@tonic-gate #if defined(TRAPDEBUG) || defined(lint)
610Sstevel@tonic-gate static int lodebug = 0;
620Sstevel@tonic-gate #else
630Sstevel@tonic-gate #define lodebug 0
640Sstevel@tonic-gate #endif /* defined(TRAPDEBUG) || defined(lint) */
650Sstevel@tonic-gate
660Sstevel@tonic-gate
670Sstevel@tonic-gate int vis1_partial_support(struct regs *rp, k_siginfo_t *siginfo, uint_t *fault);
680Sstevel@tonic-gate #pragma weak vis1_partial_support
690Sstevel@tonic-gate
700Sstevel@tonic-gate void showregs(unsigned, struct regs *, caddr_t, uint_t);
710Sstevel@tonic-gate #pragma weak showregs
720Sstevel@tonic-gate
730Sstevel@tonic-gate void trap_async_hwerr(void);
740Sstevel@tonic-gate #pragma weak trap_async_hwerr
750Sstevel@tonic-gate
760Sstevel@tonic-gate void trap_async_berr_bto(int, struct regs *);
770Sstevel@tonic-gate #pragma weak trap_async_berr_bto
780Sstevel@tonic-gate
790Sstevel@tonic-gate static enum seg_rw get_accesstype(struct regs *);
800Sstevel@tonic-gate static int nfload(struct regs *, int *);
810Sstevel@tonic-gate static int swap_nc(struct regs *, int);
820Sstevel@tonic-gate static int ldstub_nc(struct regs *, int);
830Sstevel@tonic-gate void trap_cleanup(struct regs *, uint_t, k_siginfo_t *, int);
840Sstevel@tonic-gate void trap_rtt(void);
850Sstevel@tonic-gate
860Sstevel@tonic-gate static int
die(unsigned type,struct regs * rp,caddr_t addr,uint_t mmu_fsr)870Sstevel@tonic-gate die(unsigned type, struct regs *rp, caddr_t addr, uint_t mmu_fsr)
880Sstevel@tonic-gate {
895084Sjohnlev struct panic_trap_info ti;
900Sstevel@tonic-gate
910Sstevel@tonic-gate #ifdef TRAPTRACE
920Sstevel@tonic-gate TRAPTRACE_FREEZE;
930Sstevel@tonic-gate #endif
940Sstevel@tonic-gate
950Sstevel@tonic-gate ti.trap_regs = rp;
960Sstevel@tonic-gate ti.trap_type = type;
970Sstevel@tonic-gate ti.trap_addr = addr;
980Sstevel@tonic-gate ti.trap_mmu_fsr = mmu_fsr;
990Sstevel@tonic-gate
1000Sstevel@tonic-gate curthread->t_panic_trap = &ti;
1010Sstevel@tonic-gate
1020Sstevel@tonic-gate if (type == T_DATA_MMU_MISS && addr < (caddr_t)KERNELBASE) {
1030Sstevel@tonic-gate panic("BAD TRAP: type=%x rp=%p addr=%p mmu_fsr=%x "
1040Sstevel@tonic-gate "occurred in module \"%s\" due to %s",
1050Sstevel@tonic-gate type, (void *)rp, (void *)addr, mmu_fsr,
1060Sstevel@tonic-gate mod_containing_pc((caddr_t)rp->r_pc),
1070Sstevel@tonic-gate addr < (caddr_t)PAGESIZE ?
1080Sstevel@tonic-gate "a NULL pointer dereference" :
1090Sstevel@tonic-gate "an illegal access to a user address");
1100Sstevel@tonic-gate } else {
1110Sstevel@tonic-gate panic("BAD TRAP: type=%x rp=%p addr=%p mmu_fsr=%x",
1120Sstevel@tonic-gate type, (void *)rp, (void *)addr, mmu_fsr);
1130Sstevel@tonic-gate }
1140Sstevel@tonic-gate
1150Sstevel@tonic-gate return (0); /* avoid optimization of restore in call's delay slot */
1160Sstevel@tonic-gate }
1170Sstevel@tonic-gate
1180Sstevel@tonic-gate #if defined(SF_ERRATA_23) || defined(SF_ERRATA_30) /* call ... illegal-insn */
1190Sstevel@tonic-gate int ill_calls;
1200Sstevel@tonic-gate #endif
1210Sstevel@tonic-gate
1220Sstevel@tonic-gate /*
1230Sstevel@tonic-gate * Currently, the only PREFETCH/PREFETCHA instructions which cause traps
1240Sstevel@tonic-gate * are the "strong" prefetches (fcn=20-23). But we check for all flavors of
1250Sstevel@tonic-gate * PREFETCH, in case some future variant also causes a DATA_MMU_MISS.
1260Sstevel@tonic-gate */
1270Sstevel@tonic-gate #define IS_PREFETCH(i) (((i) & 0xc1780000) == 0xc1680000)
1280Sstevel@tonic-gate
1290Sstevel@tonic-gate #define IS_FLUSH(i) (((i) & 0xc1f80000) == 0x81d80000)
1300Sstevel@tonic-gate #define IS_SWAP(i) (((i) & 0xc1f80000) == 0xc0780000)
1310Sstevel@tonic-gate #define IS_LDSTUB(i) (((i) & 0xc1f80000) == 0xc0680000)
1320Sstevel@tonic-gate #define IS_FLOAT(i) (((i) & 0x1000000) != 0)
1330Sstevel@tonic-gate #define IS_STORE(i) (((i) >> 21) & 1)
1340Sstevel@tonic-gate
1350Sstevel@tonic-gate /*
1360Sstevel@tonic-gate * Called from the trap handler when a processor trap occurs.
1370Sstevel@tonic-gate */
1380Sstevel@tonic-gate /*VARARGS2*/
1390Sstevel@tonic-gate void
trap(struct regs * rp,caddr_t addr,uint32_t type,uint32_t mmu_fsr)1400Sstevel@tonic-gate trap(struct regs *rp, caddr_t addr, uint32_t type, uint32_t mmu_fsr)
1410Sstevel@tonic-gate {
1420Sstevel@tonic-gate proc_t *p = ttoproc(curthread);
1430Sstevel@tonic-gate klwp_id_t lwp = ttolwp(curthread);
1440Sstevel@tonic-gate struct machpcb *mpcb = NULL;
1450Sstevel@tonic-gate k_siginfo_t siginfo;
1460Sstevel@tonic-gate uint_t op3, fault = 0;
1470Sstevel@tonic-gate int stepped = 0;
1480Sstevel@tonic-gate greg_t oldpc;
1490Sstevel@tonic-gate int mstate;
1500Sstevel@tonic-gate char *badaddr;
1510Sstevel@tonic-gate faultcode_t res;
1520Sstevel@tonic-gate enum fault_type fault_type;
1530Sstevel@tonic-gate enum seg_rw rw;
1540Sstevel@tonic-gate uintptr_t lofault;
1550Sstevel@tonic-gate int instr;
1560Sstevel@tonic-gate int iskernel;
1570Sstevel@tonic-gate int watchcode;
1580Sstevel@tonic-gate int watchpage;
1590Sstevel@tonic-gate extern faultcode_t pagefault(caddr_t, enum fault_type,
1605084Sjohnlev enum seg_rw, int);
161*11172SHaik.Aftandilian@Sun.COM #ifdef sun4v
162*11172SHaik.Aftandilian@Sun.COM extern boolean_t tick_stick_emulation_active;
163*11172SHaik.Aftandilian@Sun.COM #endif /* sun4v */
1640Sstevel@tonic-gate
1650Sstevel@tonic-gate CPU_STATS_ADDQ(CPU, sys, trap, 1);
1660Sstevel@tonic-gate
1670Sstevel@tonic-gate #ifdef SF_ERRATA_23 /* call causes illegal-insn */
1680Sstevel@tonic-gate ASSERT((curthread->t_schedflag & TS_DONT_SWAP) ||
1690Sstevel@tonic-gate (type == T_UNIMP_INSTR));
1700Sstevel@tonic-gate #else
1710Sstevel@tonic-gate ASSERT(curthread->t_schedflag & TS_DONT_SWAP);
1720Sstevel@tonic-gate #endif /* SF_ERRATA_23 */
1730Sstevel@tonic-gate
1740Sstevel@tonic-gate if (USERMODE(rp->r_tstate) || (type & T_USER)) {
1750Sstevel@tonic-gate /*
1760Sstevel@tonic-gate * Set lwp_state before trying to acquire any
1770Sstevel@tonic-gate * adaptive lock
1780Sstevel@tonic-gate */
1790Sstevel@tonic-gate ASSERT(lwp != NULL);
1800Sstevel@tonic-gate lwp->lwp_state = LWP_SYS;
1810Sstevel@tonic-gate /*
1820Sstevel@tonic-gate * Set up the current cred to use during this trap. u_cred
1830Sstevel@tonic-gate * no longer exists. t_cred is used instead.
1840Sstevel@tonic-gate * The current process credential applies to the thread for
1850Sstevel@tonic-gate * the entire trap. If trapping from the kernel, this
1860Sstevel@tonic-gate * should already be set up.
1870Sstevel@tonic-gate */
1880Sstevel@tonic-gate if (curthread->t_cred != p->p_cred) {
1890Sstevel@tonic-gate cred_t *oldcred = curthread->t_cred;
1900Sstevel@tonic-gate /*
1910Sstevel@tonic-gate * DTrace accesses t_cred in probe context. t_cred
1920Sstevel@tonic-gate * must always be either NULL, or point to a valid,
1930Sstevel@tonic-gate * allocated cred structure.
1940Sstevel@tonic-gate */
1950Sstevel@tonic-gate curthread->t_cred = crgetcred();
1960Sstevel@tonic-gate crfree(oldcred);
1970Sstevel@tonic-gate }
1980Sstevel@tonic-gate type |= T_USER;
1990Sstevel@tonic-gate ASSERT((type == (T_SYS_RTT_PAGE | T_USER)) ||
2005084Sjohnlev (type == (T_SYS_RTT_ALIGN | T_USER)) ||
2015084Sjohnlev lwp->lwp_regs == rp);
2020Sstevel@tonic-gate mpcb = lwptompcb(lwp);
2030Sstevel@tonic-gate switch (type) {
2040Sstevel@tonic-gate case T_WIN_OVERFLOW + T_USER:
2050Sstevel@tonic-gate case T_WIN_UNDERFLOW + T_USER:
2060Sstevel@tonic-gate case T_SYS_RTT_PAGE + T_USER:
2070Sstevel@tonic-gate case T_DATA_MMU_MISS + T_USER:
2080Sstevel@tonic-gate mstate = LMS_DFAULT;
2090Sstevel@tonic-gate break;
2100Sstevel@tonic-gate case T_INSTR_MMU_MISS + T_USER:
2110Sstevel@tonic-gate mstate = LMS_TFAULT;
2120Sstevel@tonic-gate break;
2130Sstevel@tonic-gate default:
2140Sstevel@tonic-gate mstate = LMS_TRAP;
2150Sstevel@tonic-gate break;
2160Sstevel@tonic-gate }
2170Sstevel@tonic-gate /* Kernel probe */
2180Sstevel@tonic-gate TNF_PROBE_1(thread_state, "thread", /* CSTYLED */,
2190Sstevel@tonic-gate tnf_microstate, state, (char)mstate);
2200Sstevel@tonic-gate mstate = new_mstate(curthread, mstate);
2210Sstevel@tonic-gate siginfo.si_signo = 0;
2220Sstevel@tonic-gate stepped =
2230Sstevel@tonic-gate lwp->lwp_pcb.pcb_step != STEP_NONE &&
2240Sstevel@tonic-gate ((oldpc = rp->r_pc), prundostep()) &&
2250Sstevel@tonic-gate mmu_btop((uintptr_t)addr) == mmu_btop((uintptr_t)oldpc);
2260Sstevel@tonic-gate /* this assignment must not precede call to prundostep() */
2270Sstevel@tonic-gate oldpc = rp->r_pc;
2280Sstevel@tonic-gate }
2290Sstevel@tonic-gate
2300Sstevel@tonic-gate TRACE_1(TR_FAC_TRAP, TR_C_TRAP_HANDLER_ENTER,
2315084Sjohnlev "C_trap_handler_enter:type %x", type);
2320Sstevel@tonic-gate
2330Sstevel@tonic-gate #ifdef F_DEFERRED
2340Sstevel@tonic-gate /*
2350Sstevel@tonic-gate * Take any pending floating point exceptions now.
2360Sstevel@tonic-gate * If the floating point unit has an exception to handle,
2370Sstevel@tonic-gate * just return to user-level to let the signal handler run.
2380Sstevel@tonic-gate * The instruction that got us to trap() will be reexecuted on
2390Sstevel@tonic-gate * return from the signal handler and we will trap to here again.
2400Sstevel@tonic-gate * This is necessary to disambiguate simultaneous traps which
2410Sstevel@tonic-gate * happen when a floating-point exception is pending and a
2420Sstevel@tonic-gate * machine fault is incurred.
2430Sstevel@tonic-gate */
2440Sstevel@tonic-gate if (type & USER) {
2450Sstevel@tonic-gate /*
2460Sstevel@tonic-gate * FP_TRAPPED is set only by sendsig() when it copies
2470Sstevel@tonic-gate * out the floating-point queue for the signal handler.
2480Sstevel@tonic-gate * It is set there so we can test it here and in syscall().
2490Sstevel@tonic-gate */
2500Sstevel@tonic-gate mpcb->mpcb_flags &= ~FP_TRAPPED;
2510Sstevel@tonic-gate syncfpu();
2520Sstevel@tonic-gate if (mpcb->mpcb_flags & FP_TRAPPED) {
2530Sstevel@tonic-gate /*
2540Sstevel@tonic-gate * trap() has have been called recursively and may
2550Sstevel@tonic-gate * have stopped the process, so do single step
2560Sstevel@tonic-gate * support for /proc.
2570Sstevel@tonic-gate */
2580Sstevel@tonic-gate mpcb->mpcb_flags &= ~FP_TRAPPED;
2590Sstevel@tonic-gate goto out;
2600Sstevel@tonic-gate }
2610Sstevel@tonic-gate }
2620Sstevel@tonic-gate #endif
2630Sstevel@tonic-gate switch (type) {
2640Sstevel@tonic-gate case T_DATA_MMU_MISS:
2650Sstevel@tonic-gate case T_INSTR_MMU_MISS + T_USER:
2660Sstevel@tonic-gate case T_DATA_MMU_MISS + T_USER:
2670Sstevel@tonic-gate case T_DATA_PROT + T_USER:
2680Sstevel@tonic-gate case T_AST + T_USER:
2690Sstevel@tonic-gate case T_SYS_RTT_PAGE + T_USER:
2700Sstevel@tonic-gate case T_FLUSH_PCB + T_USER:
2710Sstevel@tonic-gate case T_FLUSHW + T_USER:
2720Sstevel@tonic-gate break;
2730Sstevel@tonic-gate
2740Sstevel@tonic-gate default:
2750Sstevel@tonic-gate FTRACE_3("trap(): type=0x%lx, regs=0x%lx, addr=0x%lx",
2760Sstevel@tonic-gate (ulong_t)type, (ulong_t)rp, (ulong_t)addr);
2770Sstevel@tonic-gate break;
2780Sstevel@tonic-gate }
2790Sstevel@tonic-gate
2800Sstevel@tonic-gate switch (type) {
2810Sstevel@tonic-gate
2820Sstevel@tonic-gate default:
2830Sstevel@tonic-gate /*
2840Sstevel@tonic-gate * Check for user software trap.
2850Sstevel@tonic-gate */
2860Sstevel@tonic-gate if (type & T_USER) {
2870Sstevel@tonic-gate if (tudebug)
2880Sstevel@tonic-gate showregs(type, rp, (caddr_t)0, 0);
2890Sstevel@tonic-gate if ((type & ~T_USER) >= T_SOFTWARE_TRAP) {
2900Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
2910Sstevel@tonic-gate siginfo.si_signo = SIGILL;
2920Sstevel@tonic-gate siginfo.si_code = ILL_ILLTRP;
2930Sstevel@tonic-gate siginfo.si_addr = (caddr_t)rp->r_pc;
2940Sstevel@tonic-gate siginfo.si_trapno = type &~ T_USER;
2950Sstevel@tonic-gate fault = FLTILL;
2960Sstevel@tonic-gate break;
2970Sstevel@tonic-gate }
2980Sstevel@tonic-gate }
2990Sstevel@tonic-gate addr = (caddr_t)rp->r_pc;
3000Sstevel@tonic-gate (void) die(type, rp, addr, 0);
3010Sstevel@tonic-gate /*NOTREACHED*/
3020Sstevel@tonic-gate
3030Sstevel@tonic-gate case T_ALIGNMENT: /* supv alignment error */
3040Sstevel@tonic-gate if (nfload(rp, NULL))
3050Sstevel@tonic-gate goto cleanup;
3060Sstevel@tonic-gate
3070Sstevel@tonic-gate if (curthread->t_lofault) {
3080Sstevel@tonic-gate if (lodebug) {
3090Sstevel@tonic-gate showregs(type, rp, addr, 0);
3100Sstevel@tonic-gate traceback((caddr_t)rp->r_sp);
3110Sstevel@tonic-gate }
3120Sstevel@tonic-gate rp->r_g1 = EFAULT;
3130Sstevel@tonic-gate rp->r_pc = curthread->t_lofault;
3140Sstevel@tonic-gate rp->r_npc = rp->r_pc + 4;
3150Sstevel@tonic-gate goto cleanup;
3160Sstevel@tonic-gate }
3170Sstevel@tonic-gate (void) die(type, rp, addr, 0);
3180Sstevel@tonic-gate /*NOTREACHED*/
3190Sstevel@tonic-gate
3200Sstevel@tonic-gate case T_INSTR_EXCEPTION: /* sys instruction access exception */
3210Sstevel@tonic-gate addr = (caddr_t)rp->r_pc;
3220Sstevel@tonic-gate (void) die(type, rp, addr, mmu_fsr);
3230Sstevel@tonic-gate /*NOTREACHED*/
3240Sstevel@tonic-gate
3250Sstevel@tonic-gate case T_INSTR_MMU_MISS: /* sys instruction mmu miss */
3260Sstevel@tonic-gate addr = (caddr_t)rp->r_pc;
3270Sstevel@tonic-gate (void) die(type, rp, addr, 0);
3280Sstevel@tonic-gate /*NOTREACHED*/
3290Sstevel@tonic-gate
3300Sstevel@tonic-gate case T_DATA_EXCEPTION: /* system data access exception */
3310Sstevel@tonic-gate switch (X_FAULT_TYPE(mmu_fsr)) {
3320Sstevel@tonic-gate case FT_RANGE:
3330Sstevel@tonic-gate /*
3340Sstevel@tonic-gate * This happens when we attempt to dereference an
3350Sstevel@tonic-gate * address in the address hole. If t_ontrap is set,
3360Sstevel@tonic-gate * then break and fall through to T_DATA_MMU_MISS /
3370Sstevel@tonic-gate * T_DATA_PROT case below. If lofault is set, then
3380Sstevel@tonic-gate * honour it (perhaps the user gave us a bogus
3390Sstevel@tonic-gate * address in the hole to copyin from or copyout to?)
3400Sstevel@tonic-gate */
3410Sstevel@tonic-gate
3420Sstevel@tonic-gate if (curthread->t_ontrap != NULL)
3430Sstevel@tonic-gate break;
3440Sstevel@tonic-gate
3450Sstevel@tonic-gate addr = (caddr_t)((uintptr_t)addr & TAGACC_VADDR_MASK);
3460Sstevel@tonic-gate if (curthread->t_lofault) {
3470Sstevel@tonic-gate if (lodebug) {
3480Sstevel@tonic-gate showregs(type, rp, addr, 0);
3490Sstevel@tonic-gate traceback((caddr_t)rp->r_sp);
3500Sstevel@tonic-gate }
3510Sstevel@tonic-gate rp->r_g1 = EFAULT;
3520Sstevel@tonic-gate rp->r_pc = curthread->t_lofault;
3530Sstevel@tonic-gate rp->r_npc = rp->r_pc + 4;
3540Sstevel@tonic-gate goto cleanup;
3550Sstevel@tonic-gate }
3560Sstevel@tonic-gate (void) die(type, rp, addr, mmu_fsr);
3570Sstevel@tonic-gate /*NOTREACHED*/
3580Sstevel@tonic-gate
3590Sstevel@tonic-gate case FT_PRIV:
3600Sstevel@tonic-gate /*
3610Sstevel@tonic-gate * This can happen if we access ASI_USER from a kernel
3620Sstevel@tonic-gate * thread. To support pxfs, we need to honor lofault if
3630Sstevel@tonic-gate * we're doing a copyin/copyout from a kernel thread.
3640Sstevel@tonic-gate */
3650Sstevel@tonic-gate
3660Sstevel@tonic-gate if (nfload(rp, NULL))
3670Sstevel@tonic-gate goto cleanup;
3680Sstevel@tonic-gate addr = (caddr_t)((uintptr_t)addr & TAGACC_VADDR_MASK);
3690Sstevel@tonic-gate if (curthread->t_lofault) {
3700Sstevel@tonic-gate if (lodebug) {
3710Sstevel@tonic-gate showregs(type, rp, addr, 0);
3720Sstevel@tonic-gate traceback((caddr_t)rp->r_sp);
3730Sstevel@tonic-gate }
3740Sstevel@tonic-gate rp->r_g1 = EFAULT;
3750Sstevel@tonic-gate rp->r_pc = curthread->t_lofault;
3760Sstevel@tonic-gate rp->r_npc = rp->r_pc + 4;
3770Sstevel@tonic-gate goto cleanup;
3780Sstevel@tonic-gate }
3790Sstevel@tonic-gate (void) die(type, rp, addr, mmu_fsr);
3800Sstevel@tonic-gate /*NOTREACHED*/
3810Sstevel@tonic-gate
3820Sstevel@tonic-gate default:
3830Sstevel@tonic-gate if (nfload(rp, NULL))
3840Sstevel@tonic-gate goto cleanup;
3850Sstevel@tonic-gate addr = (caddr_t)((uintptr_t)addr & TAGACC_VADDR_MASK);
3860Sstevel@tonic-gate (void) die(type, rp, addr, mmu_fsr);
3870Sstevel@tonic-gate /*NOTREACHED*/
3880Sstevel@tonic-gate
3890Sstevel@tonic-gate case FT_NFO:
3900Sstevel@tonic-gate break;
3910Sstevel@tonic-gate }
3920Sstevel@tonic-gate /* fall into ... */
3930Sstevel@tonic-gate
3940Sstevel@tonic-gate case T_DATA_MMU_MISS: /* system data mmu miss */
3950Sstevel@tonic-gate case T_DATA_PROT: /* system data protection fault */
3960Sstevel@tonic-gate if (nfload(rp, &instr))
3970Sstevel@tonic-gate goto cleanup;
3980Sstevel@tonic-gate
3990Sstevel@tonic-gate /*
4000Sstevel@tonic-gate * If we're under on_trap() protection (see <sys/ontrap.h>),
4010Sstevel@tonic-gate * set ot_trap and return from the trap to the trampoline.
4020Sstevel@tonic-gate */
4030Sstevel@tonic-gate if (curthread->t_ontrap != NULL) {
4040Sstevel@tonic-gate on_trap_data_t *otp = curthread->t_ontrap;
4050Sstevel@tonic-gate
4060Sstevel@tonic-gate TRACE_0(TR_FAC_TRAP, TR_C_TRAP_HANDLER_EXIT,
4075084Sjohnlev "C_trap_handler_exit");
4080Sstevel@tonic-gate TRACE_0(TR_FAC_TRAP, TR_TRAP_END, "trap_end");
4090Sstevel@tonic-gate
4100Sstevel@tonic-gate if (otp->ot_prot & OT_DATA_ACCESS) {
4110Sstevel@tonic-gate otp->ot_trap |= OT_DATA_ACCESS;
4120Sstevel@tonic-gate rp->r_pc = otp->ot_trampoline;
4130Sstevel@tonic-gate rp->r_npc = rp->r_pc + 4;
4140Sstevel@tonic-gate goto cleanup;
4150Sstevel@tonic-gate }
4160Sstevel@tonic-gate }
4170Sstevel@tonic-gate lofault = curthread->t_lofault;
4180Sstevel@tonic-gate curthread->t_lofault = 0;
4190Sstevel@tonic-gate
4200Sstevel@tonic-gate mstate = new_mstate(curthread, LMS_KFAULT);
4210Sstevel@tonic-gate
4220Sstevel@tonic-gate switch (type) {
4230Sstevel@tonic-gate case T_DATA_PROT:
4240Sstevel@tonic-gate fault_type = F_PROT;
4250Sstevel@tonic-gate rw = S_WRITE;
4260Sstevel@tonic-gate break;
4270Sstevel@tonic-gate case T_INSTR_MMU_MISS:
4280Sstevel@tonic-gate fault_type = F_INVAL;
4290Sstevel@tonic-gate rw = S_EXEC;
4300Sstevel@tonic-gate break;
4310Sstevel@tonic-gate case T_DATA_MMU_MISS:
4320Sstevel@tonic-gate case T_DATA_EXCEPTION:
4330Sstevel@tonic-gate /*
4340Sstevel@tonic-gate * The hardware doesn't update the sfsr on mmu
4350Sstevel@tonic-gate * misses so it is not easy to find out whether
4360Sstevel@tonic-gate * the access was a read or a write so we need
4370Sstevel@tonic-gate * to decode the actual instruction.
4380Sstevel@tonic-gate */
4390Sstevel@tonic-gate fault_type = F_INVAL;
4400Sstevel@tonic-gate rw = get_accesstype(rp);
4410Sstevel@tonic-gate break;
4420Sstevel@tonic-gate default:
4430Sstevel@tonic-gate cmn_err(CE_PANIC, "trap: unknown type %x", type);
4440Sstevel@tonic-gate break;
4450Sstevel@tonic-gate }
4460Sstevel@tonic-gate /*
4470Sstevel@tonic-gate * We determine if access was done to kernel or user
4480Sstevel@tonic-gate * address space. The addr passed into trap is really the
4490Sstevel@tonic-gate * tag access register.
4500Sstevel@tonic-gate */
4510Sstevel@tonic-gate iskernel = (((uintptr_t)addr & TAGACC_CTX_MASK) == KCONTEXT);
4520Sstevel@tonic-gate addr = (caddr_t)((uintptr_t)addr & TAGACC_VADDR_MASK);
4530Sstevel@tonic-gate
4540Sstevel@tonic-gate res = pagefault(addr, fault_type, rw, iskernel);
4550Sstevel@tonic-gate if (!iskernel && res == FC_NOMAP &&
4560Sstevel@tonic-gate addr < p->p_usrstack && grow(addr))
4570Sstevel@tonic-gate res = 0;
4580Sstevel@tonic-gate
4590Sstevel@tonic-gate (void) new_mstate(curthread, mstate);
4600Sstevel@tonic-gate
4610Sstevel@tonic-gate /*
4620Sstevel@tonic-gate * Restore lofault. If we resolved the fault, exit.
4630Sstevel@tonic-gate * If we didn't and lofault wasn't set, die.
4640Sstevel@tonic-gate */
4650Sstevel@tonic-gate curthread->t_lofault = lofault;
4660Sstevel@tonic-gate
4670Sstevel@tonic-gate if (res == 0)
4680Sstevel@tonic-gate goto cleanup;
4690Sstevel@tonic-gate
4700Sstevel@tonic-gate if (IS_PREFETCH(instr)) {
4710Sstevel@tonic-gate /* skip prefetch instructions in kernel-land */
4720Sstevel@tonic-gate rp->r_pc = rp->r_npc;
4730Sstevel@tonic-gate rp->r_npc += 4;
4740Sstevel@tonic-gate goto cleanup;
4750Sstevel@tonic-gate }
4760Sstevel@tonic-gate
4770Sstevel@tonic-gate if ((lofault == 0 || lodebug) &&
4780Sstevel@tonic-gate (calc_memaddr(rp, &badaddr) == SIMU_SUCCESS))
4790Sstevel@tonic-gate addr = badaddr;
4800Sstevel@tonic-gate if (lofault == 0)
4810Sstevel@tonic-gate (void) die(type, rp, addr, 0);
4820Sstevel@tonic-gate /*
4830Sstevel@tonic-gate * Cannot resolve fault. Return to lofault.
4840Sstevel@tonic-gate */
4850Sstevel@tonic-gate if (lodebug) {
4860Sstevel@tonic-gate showregs(type, rp, addr, 0);
4870Sstevel@tonic-gate traceback((caddr_t)rp->r_sp);
4880Sstevel@tonic-gate }
4890Sstevel@tonic-gate if (FC_CODE(res) == FC_OBJERR)
4900Sstevel@tonic-gate res = FC_ERRNO(res);
4910Sstevel@tonic-gate else
4920Sstevel@tonic-gate res = EFAULT;
4930Sstevel@tonic-gate rp->r_g1 = res;
4940Sstevel@tonic-gate rp->r_pc = curthread->t_lofault;
4950Sstevel@tonic-gate rp->r_npc = curthread->t_lofault + 4;
4960Sstevel@tonic-gate goto cleanup;
4970Sstevel@tonic-gate
4980Sstevel@tonic-gate case T_INSTR_EXCEPTION + T_USER: /* user insn access exception */
4990Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
5000Sstevel@tonic-gate siginfo.si_addr = (caddr_t)rp->r_pc;
5010Sstevel@tonic-gate siginfo.si_signo = SIGSEGV;
5020Sstevel@tonic-gate siginfo.si_code = X_FAULT_TYPE(mmu_fsr) == FT_PRIV ?
5030Sstevel@tonic-gate SEGV_ACCERR : SEGV_MAPERR;
5040Sstevel@tonic-gate fault = FLTBOUNDS;
5050Sstevel@tonic-gate break;
5060Sstevel@tonic-gate
5070Sstevel@tonic-gate case T_WIN_OVERFLOW + T_USER: /* window overflow in ??? */
5080Sstevel@tonic-gate case T_WIN_UNDERFLOW + T_USER: /* window underflow in ??? */
5090Sstevel@tonic-gate case T_SYS_RTT_PAGE + T_USER: /* window underflow in user_rtt */
5100Sstevel@tonic-gate case T_INSTR_MMU_MISS + T_USER: /* user instruction mmu miss */
5110Sstevel@tonic-gate case T_DATA_MMU_MISS + T_USER: /* user data mmu miss */
5120Sstevel@tonic-gate case T_DATA_PROT + T_USER: /* user data protection fault */
5130Sstevel@tonic-gate switch (type) {
5140Sstevel@tonic-gate case T_INSTR_MMU_MISS + T_USER:
5150Sstevel@tonic-gate addr = (caddr_t)rp->r_pc;
5160Sstevel@tonic-gate fault_type = F_INVAL;
5170Sstevel@tonic-gate rw = S_EXEC;
5180Sstevel@tonic-gate break;
5190Sstevel@tonic-gate
5200Sstevel@tonic-gate case T_DATA_MMU_MISS + T_USER:
5210Sstevel@tonic-gate addr = (caddr_t)((uintptr_t)addr & TAGACC_VADDR_MASK);
5220Sstevel@tonic-gate fault_type = F_INVAL;
5230Sstevel@tonic-gate /*
5240Sstevel@tonic-gate * The hardware doesn't update the sfsr on mmu misses
5250Sstevel@tonic-gate * so it is not easy to find out whether the access
5260Sstevel@tonic-gate * was a read or a write so we need to decode the
5270Sstevel@tonic-gate * actual instruction. XXX BUGLY HW
5280Sstevel@tonic-gate */
5290Sstevel@tonic-gate rw = get_accesstype(rp);
5300Sstevel@tonic-gate break;
5310Sstevel@tonic-gate
5320Sstevel@tonic-gate case T_DATA_PROT + T_USER:
5330Sstevel@tonic-gate addr = (caddr_t)((uintptr_t)addr & TAGACC_VADDR_MASK);
5340Sstevel@tonic-gate fault_type = F_PROT;
5350Sstevel@tonic-gate rw = S_WRITE;
5360Sstevel@tonic-gate break;
5370Sstevel@tonic-gate
5380Sstevel@tonic-gate case T_WIN_OVERFLOW + T_USER:
5390Sstevel@tonic-gate addr = (caddr_t)((uintptr_t)addr & TAGACC_VADDR_MASK);
5400Sstevel@tonic-gate fault_type = F_INVAL;
5410Sstevel@tonic-gate rw = S_WRITE;
5420Sstevel@tonic-gate break;
5430Sstevel@tonic-gate
5440Sstevel@tonic-gate case T_WIN_UNDERFLOW + T_USER:
5450Sstevel@tonic-gate case T_SYS_RTT_PAGE + T_USER:
5460Sstevel@tonic-gate addr = (caddr_t)((uintptr_t)addr & TAGACC_VADDR_MASK);
5470Sstevel@tonic-gate fault_type = F_INVAL;
5480Sstevel@tonic-gate rw = S_READ;
5490Sstevel@tonic-gate break;
5500Sstevel@tonic-gate
5510Sstevel@tonic-gate default:
5520Sstevel@tonic-gate cmn_err(CE_PANIC, "trap: unknown type %x", type);
5530Sstevel@tonic-gate break;
5540Sstevel@tonic-gate }
5550Sstevel@tonic-gate
5560Sstevel@tonic-gate /*
5570Sstevel@tonic-gate * If we are single stepping do not call pagefault
5580Sstevel@tonic-gate */
5590Sstevel@tonic-gate if (stepped) {
5600Sstevel@tonic-gate res = FC_NOMAP;
5610Sstevel@tonic-gate } else {
5620Sstevel@tonic-gate caddr_t vaddr = addr;
5630Sstevel@tonic-gate size_t sz;
5640Sstevel@tonic-gate int ta;
5650Sstevel@tonic-gate
5660Sstevel@tonic-gate ASSERT(!(curthread->t_flag & T_WATCHPT));
5670Sstevel@tonic-gate watchpage = (pr_watch_active(p) &&
5685084Sjohnlev type != T_WIN_OVERFLOW + T_USER &&
5695084Sjohnlev type != T_WIN_UNDERFLOW + T_USER &&
5705084Sjohnlev type != T_SYS_RTT_PAGE + T_USER &&
5715084Sjohnlev pr_is_watchpage(addr, rw));
5720Sstevel@tonic-gate
5730Sstevel@tonic-gate if (!watchpage ||
5740Sstevel@tonic-gate (sz = instr_size(rp, &vaddr, rw)) <= 0)
5750Sstevel@tonic-gate /* EMPTY */;
5760Sstevel@tonic-gate else if ((watchcode = pr_is_watchpoint(&vaddr, &ta,
5770Sstevel@tonic-gate sz, NULL, rw)) != 0) {
5780Sstevel@tonic-gate if (ta) {
5790Sstevel@tonic-gate do_watch_step(vaddr, sz, rw,
5805084Sjohnlev watchcode, rp->r_pc);
5810Sstevel@tonic-gate fault_type = F_INVAL;
5820Sstevel@tonic-gate } else {
5830Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
5840Sstevel@tonic-gate siginfo.si_signo = SIGTRAP;
5850Sstevel@tonic-gate siginfo.si_code = watchcode;
5860Sstevel@tonic-gate siginfo.si_addr = vaddr;
5870Sstevel@tonic-gate siginfo.si_trapafter = 0;
5880Sstevel@tonic-gate siginfo.si_pc = (caddr_t)rp->r_pc;
5890Sstevel@tonic-gate fault = FLTWATCH;
5900Sstevel@tonic-gate break;
5910Sstevel@tonic-gate }
5920Sstevel@tonic-gate } else {
5930Sstevel@tonic-gate if (rw != S_EXEC &&
5940Sstevel@tonic-gate pr_watch_emul(rp, vaddr, rw))
5950Sstevel@tonic-gate goto out;
5960Sstevel@tonic-gate do_watch_step(vaddr, sz, rw, 0, 0);
5970Sstevel@tonic-gate fault_type = F_INVAL;
5980Sstevel@tonic-gate }
5990Sstevel@tonic-gate
6000Sstevel@tonic-gate if (pr_watch_active(p) &&
6010Sstevel@tonic-gate (type == T_WIN_OVERFLOW + T_USER ||
6020Sstevel@tonic-gate type == T_WIN_UNDERFLOW + T_USER ||
6030Sstevel@tonic-gate type == T_SYS_RTT_PAGE + T_USER)) {
6040Sstevel@tonic-gate int dotwo = (type == T_WIN_UNDERFLOW + T_USER);
6050Sstevel@tonic-gate if (copy_return_window(dotwo))
6060Sstevel@tonic-gate goto out;
6070Sstevel@tonic-gate fault_type = F_INVAL;
6080Sstevel@tonic-gate }
6090Sstevel@tonic-gate
6100Sstevel@tonic-gate res = pagefault(addr, fault_type, rw, 0);
6110Sstevel@tonic-gate
6120Sstevel@tonic-gate /*
6130Sstevel@tonic-gate * If pagefault succeed, ok.
6140Sstevel@tonic-gate * Otherwise grow the stack automatically.
6150Sstevel@tonic-gate */
6160Sstevel@tonic-gate if (res == 0 ||
6170Sstevel@tonic-gate (res == FC_NOMAP &&
6180Sstevel@tonic-gate type != T_INSTR_MMU_MISS + T_USER &&
6190Sstevel@tonic-gate addr < p->p_usrstack &&
6200Sstevel@tonic-gate grow(addr))) {
6210Sstevel@tonic-gate int ismem = prismember(&p->p_fltmask, FLTPAGE);
6220Sstevel@tonic-gate
6230Sstevel@tonic-gate /*
6240Sstevel@tonic-gate * instr_size() is used to get the exact
6250Sstevel@tonic-gate * address of the fault, instead of the
6260Sstevel@tonic-gate * page of the fault. Unfortunately it is
6270Sstevel@tonic-gate * very slow, and this is an important
6280Sstevel@tonic-gate * code path. Don't call it unless
6290Sstevel@tonic-gate * correctness is needed. ie. if FLTPAGE
6300Sstevel@tonic-gate * is set, or we're profiling.
6310Sstevel@tonic-gate */
6320Sstevel@tonic-gate
6330Sstevel@tonic-gate if (curthread->t_rprof != NULL || ismem)
6340Sstevel@tonic-gate (void) instr_size(rp, &addr, rw);
6350Sstevel@tonic-gate
6360Sstevel@tonic-gate lwp->lwp_lastfault = FLTPAGE;
6370Sstevel@tonic-gate lwp->lwp_lastfaddr = addr;
6380Sstevel@tonic-gate
6390Sstevel@tonic-gate if (ismem) {
6400Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
6410Sstevel@tonic-gate siginfo.si_addr = addr;
6420Sstevel@tonic-gate (void) stop_on_fault(FLTPAGE, &siginfo);
6430Sstevel@tonic-gate }
6440Sstevel@tonic-gate goto out;
6450Sstevel@tonic-gate }
6460Sstevel@tonic-gate
6470Sstevel@tonic-gate if (type != (T_INSTR_MMU_MISS + T_USER)) {
6480Sstevel@tonic-gate /*
6490Sstevel@tonic-gate * check for non-faulting loads, also
6500Sstevel@tonic-gate * fetch the instruction to check for
6510Sstevel@tonic-gate * flush
6520Sstevel@tonic-gate */
6530Sstevel@tonic-gate if (nfload(rp, &instr))
6540Sstevel@tonic-gate goto out;
6550Sstevel@tonic-gate
6560Sstevel@tonic-gate /* skip userland prefetch instructions */
6570Sstevel@tonic-gate if (IS_PREFETCH(instr)) {
6580Sstevel@tonic-gate rp->r_pc = rp->r_npc;
6590Sstevel@tonic-gate rp->r_npc += 4;
6600Sstevel@tonic-gate goto out;
6610Sstevel@tonic-gate /*NOTREACHED*/
6620Sstevel@tonic-gate }
6630Sstevel@tonic-gate
6640Sstevel@tonic-gate /*
6650Sstevel@tonic-gate * check if the instruction was a
6660Sstevel@tonic-gate * flush. ABI allows users to specify
6670Sstevel@tonic-gate * an illegal address on the flush
6680Sstevel@tonic-gate * instruction so we simply return in
6690Sstevel@tonic-gate * this case.
6700Sstevel@tonic-gate *
6710Sstevel@tonic-gate * NB: the hardware should set a bit
6720Sstevel@tonic-gate * indicating this trap was caused by
6730Sstevel@tonic-gate * a flush instruction. Instruction
6740Sstevel@tonic-gate * decoding is bugly!
6750Sstevel@tonic-gate */
6760Sstevel@tonic-gate if (IS_FLUSH(instr)) {
6770Sstevel@tonic-gate /* skip the flush instruction */
6780Sstevel@tonic-gate rp->r_pc = rp->r_npc;
6790Sstevel@tonic-gate rp->r_npc += 4;
6800Sstevel@tonic-gate goto out;
6810Sstevel@tonic-gate /*NOTREACHED*/
6820Sstevel@tonic-gate }
6830Sstevel@tonic-gate } else if (res == FC_PROT) {
6840Sstevel@tonic-gate report_stack_exec(p, addr);
6850Sstevel@tonic-gate }
6860Sstevel@tonic-gate
6870Sstevel@tonic-gate if (tudebug)
6880Sstevel@tonic-gate showregs(type, rp, addr, 0);
6890Sstevel@tonic-gate }
6900Sstevel@tonic-gate
6910Sstevel@tonic-gate /*
6920Sstevel@tonic-gate * In the case where both pagefault and grow fail,
6930Sstevel@tonic-gate * set the code to the value provided by pagefault.
6940Sstevel@tonic-gate */
6950Sstevel@tonic-gate (void) instr_size(rp, &addr, rw);
6960Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
6970Sstevel@tonic-gate siginfo.si_addr = addr;
6980Sstevel@tonic-gate if (FC_CODE(res) == FC_OBJERR) {
6990Sstevel@tonic-gate siginfo.si_errno = FC_ERRNO(res);
7000Sstevel@tonic-gate if (siginfo.si_errno != EINTR) {
7010Sstevel@tonic-gate siginfo.si_signo = SIGBUS;
7020Sstevel@tonic-gate siginfo.si_code = BUS_OBJERR;
7030Sstevel@tonic-gate fault = FLTACCESS;
7040Sstevel@tonic-gate }
7050Sstevel@tonic-gate } else { /* FC_NOMAP || FC_PROT */
7060Sstevel@tonic-gate siginfo.si_signo = SIGSEGV;
7070Sstevel@tonic-gate siginfo.si_code = (res == FC_NOMAP) ?
7085084Sjohnlev SEGV_MAPERR : SEGV_ACCERR;
7090Sstevel@tonic-gate fault = FLTBOUNDS;
7100Sstevel@tonic-gate }
7110Sstevel@tonic-gate /*
7120Sstevel@tonic-gate * If this is the culmination of a single-step,
7130Sstevel@tonic-gate * reset the addr, code, signal and fault to
7140Sstevel@tonic-gate * indicate a hardware trace trap.
7150Sstevel@tonic-gate */
7160Sstevel@tonic-gate if (stepped) {
7170Sstevel@tonic-gate pcb_t *pcb = &lwp->lwp_pcb;
7180Sstevel@tonic-gate
7190Sstevel@tonic-gate siginfo.si_signo = 0;
7200Sstevel@tonic-gate fault = 0;
7210Sstevel@tonic-gate if (pcb->pcb_step == STEP_WASACTIVE) {
7220Sstevel@tonic-gate pcb->pcb_step = STEP_NONE;
7230Sstevel@tonic-gate pcb->pcb_tracepc = NULL;
7240Sstevel@tonic-gate oldpc = rp->r_pc - 4;
7250Sstevel@tonic-gate }
7260Sstevel@tonic-gate /*
7270Sstevel@tonic-gate * If both NORMAL_STEP and WATCH_STEP are in
7282712Snn35248 * effect, give precedence to WATCH_STEP.
7290Sstevel@tonic-gate * One or the other must be set at this point.
7300Sstevel@tonic-gate */
7310Sstevel@tonic-gate ASSERT(pcb->pcb_flags & (NORMAL_STEP|WATCH_STEP));
7322712Snn35248 if ((fault = undo_watch_step(&siginfo)) == 0 &&
7332712Snn35248 (pcb->pcb_flags & NORMAL_STEP)) {
7340Sstevel@tonic-gate siginfo.si_signo = SIGTRAP;
7350Sstevel@tonic-gate siginfo.si_code = TRAP_TRACE;
7360Sstevel@tonic-gate siginfo.si_addr = (caddr_t)rp->r_pc;
7370Sstevel@tonic-gate fault = FLTTRACE;
7380Sstevel@tonic-gate }
7390Sstevel@tonic-gate pcb->pcb_flags &= ~(NORMAL_STEP|WATCH_STEP);
7400Sstevel@tonic-gate }
7410Sstevel@tonic-gate break;
7420Sstevel@tonic-gate
7430Sstevel@tonic-gate case T_DATA_EXCEPTION + T_USER: /* user data access exception */
7440Sstevel@tonic-gate
7450Sstevel@tonic-gate if (&vis1_partial_support != NULL) {
7460Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
7470Sstevel@tonic-gate if (vis1_partial_support(rp,
7480Sstevel@tonic-gate &siginfo, &fault) == 0)
7490Sstevel@tonic-gate goto out;
7500Sstevel@tonic-gate }
7510Sstevel@tonic-gate
7520Sstevel@tonic-gate if (nfload(rp, &instr))
7530Sstevel@tonic-gate goto out;
7540Sstevel@tonic-gate if (IS_FLUSH(instr)) {
7550Sstevel@tonic-gate /* skip the flush instruction */
7560Sstevel@tonic-gate rp->r_pc = rp->r_npc;
7570Sstevel@tonic-gate rp->r_npc += 4;
7580Sstevel@tonic-gate goto out;
7590Sstevel@tonic-gate /*NOTREACHED*/
7600Sstevel@tonic-gate }
7610Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
7620Sstevel@tonic-gate siginfo.si_addr = addr;
7630Sstevel@tonic-gate switch (X_FAULT_TYPE(mmu_fsr)) {
7640Sstevel@tonic-gate case FT_ATOMIC_NC:
7650Sstevel@tonic-gate if ((IS_SWAP(instr) && swap_nc(rp, instr)) ||
7660Sstevel@tonic-gate (IS_LDSTUB(instr) && ldstub_nc(rp, instr))) {
7670Sstevel@tonic-gate /* skip the atomic */
7680Sstevel@tonic-gate rp->r_pc = rp->r_npc;
7690Sstevel@tonic-gate rp->r_npc += 4;
7700Sstevel@tonic-gate goto out;
7710Sstevel@tonic-gate }
7720Sstevel@tonic-gate /* fall into ... */
7730Sstevel@tonic-gate case FT_PRIV:
7740Sstevel@tonic-gate siginfo.si_signo = SIGSEGV;
7750Sstevel@tonic-gate siginfo.si_code = SEGV_ACCERR;
7760Sstevel@tonic-gate fault = FLTBOUNDS;
7770Sstevel@tonic-gate break;
7780Sstevel@tonic-gate case FT_SPEC_LD:
7790Sstevel@tonic-gate case FT_ILL_ALT:
7800Sstevel@tonic-gate siginfo.si_signo = SIGILL;
7810Sstevel@tonic-gate siginfo.si_code = ILL_ILLADR;
7820Sstevel@tonic-gate fault = FLTILL;
7830Sstevel@tonic-gate break;
7840Sstevel@tonic-gate default:
7850Sstevel@tonic-gate siginfo.si_signo = SIGSEGV;
7860Sstevel@tonic-gate siginfo.si_code = SEGV_MAPERR;
7870Sstevel@tonic-gate fault = FLTBOUNDS;
7880Sstevel@tonic-gate break;
7890Sstevel@tonic-gate }
7900Sstevel@tonic-gate break;
7910Sstevel@tonic-gate
7920Sstevel@tonic-gate case T_SYS_RTT_ALIGN + T_USER: /* user alignment error */
7930Sstevel@tonic-gate case T_ALIGNMENT + T_USER: /* user alignment error */
7940Sstevel@tonic-gate if (tudebug)
7950Sstevel@tonic-gate showregs(type, rp, addr, 0);
7960Sstevel@tonic-gate /*
7970Sstevel@tonic-gate * If the user has to do unaligned references
7980Sstevel@tonic-gate * the ugly stuff gets done here.
7990Sstevel@tonic-gate */
8000Sstevel@tonic-gate alignfaults++;
8010Sstevel@tonic-gate if (&vis1_partial_support != NULL) {
8020Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
8030Sstevel@tonic-gate if (vis1_partial_support(rp,
8040Sstevel@tonic-gate &siginfo, &fault) == 0)
8050Sstevel@tonic-gate goto out;
8060Sstevel@tonic-gate }
8070Sstevel@tonic-gate
8080Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
8090Sstevel@tonic-gate if (type == T_SYS_RTT_ALIGN + T_USER) {
8102458Smb158278 if (nfload(rp, NULL))
8112458Smb158278 goto out;
8120Sstevel@tonic-gate /*
8130Sstevel@tonic-gate * Can't do unaligned stack access
8140Sstevel@tonic-gate */
8150Sstevel@tonic-gate siginfo.si_signo = SIGBUS;
8160Sstevel@tonic-gate siginfo.si_code = BUS_ADRALN;
8170Sstevel@tonic-gate siginfo.si_addr = addr;
8180Sstevel@tonic-gate fault = FLTACCESS;
8190Sstevel@tonic-gate break;
8200Sstevel@tonic-gate }
8212458Smb158278
8222458Smb158278 /*
8232458Smb158278 * Try to fix alignment before non-faulting load test.
8242458Smb158278 */
8250Sstevel@tonic-gate if (p->p_fixalignment) {
8260Sstevel@tonic-gate if (do_unaligned(rp, &badaddr) == SIMU_SUCCESS) {
8270Sstevel@tonic-gate rp->r_pc = rp->r_npc;
8280Sstevel@tonic-gate rp->r_npc += 4;
8290Sstevel@tonic-gate goto out;
8300Sstevel@tonic-gate }
8312458Smb158278 if (nfload(rp, NULL))
8322458Smb158278 goto out;
8330Sstevel@tonic-gate siginfo.si_signo = SIGSEGV;
8340Sstevel@tonic-gate siginfo.si_code = SEGV_MAPERR;
8350Sstevel@tonic-gate siginfo.si_addr = badaddr;
8360Sstevel@tonic-gate fault = FLTBOUNDS;
8370Sstevel@tonic-gate } else {
8382458Smb158278 if (nfload(rp, NULL))
8392458Smb158278 goto out;
8400Sstevel@tonic-gate siginfo.si_signo = SIGBUS;
8410Sstevel@tonic-gate siginfo.si_code = BUS_ADRALN;
8420Sstevel@tonic-gate if (rp->r_pc & 3) { /* offending address, if pc */
8430Sstevel@tonic-gate siginfo.si_addr = (caddr_t)rp->r_pc;
8440Sstevel@tonic-gate } else {
8450Sstevel@tonic-gate if (calc_memaddr(rp, &badaddr) == SIMU_UNALIGN)
8460Sstevel@tonic-gate siginfo.si_addr = badaddr;
8470Sstevel@tonic-gate else
8480Sstevel@tonic-gate siginfo.si_addr = (caddr_t)rp->r_pc;
8490Sstevel@tonic-gate }
8500Sstevel@tonic-gate fault = FLTACCESS;
8510Sstevel@tonic-gate }
8520Sstevel@tonic-gate break;
8530Sstevel@tonic-gate
8540Sstevel@tonic-gate case T_PRIV_INSTR + T_USER: /* privileged instruction fault */
8550Sstevel@tonic-gate if (tudebug)
8560Sstevel@tonic-gate showregs(type, rp, (caddr_t)0, 0);
857*11172SHaik.Aftandilian@Sun.COM
8580Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
859*11172SHaik.Aftandilian@Sun.COM #ifdef sun4v
860*11172SHaik.Aftandilian@Sun.COM /*
861*11172SHaik.Aftandilian@Sun.COM * If this instruction fault is a non-privileged %tick
862*11172SHaik.Aftandilian@Sun.COM * or %stick trap, and %tick/%stick user emulation is
863*11172SHaik.Aftandilian@Sun.COM * enabled as a result of an OS suspend, then simulate
864*11172SHaik.Aftandilian@Sun.COM * the register read. We rely on simulate_rdtick to fail
865*11172SHaik.Aftandilian@Sun.COM * if the instruction is not a %tick or %stick read,
866*11172SHaik.Aftandilian@Sun.COM * causing us to fall through to the normal privileged
867*11172SHaik.Aftandilian@Sun.COM * instruction handling.
868*11172SHaik.Aftandilian@Sun.COM */
869*11172SHaik.Aftandilian@Sun.COM if (tick_stick_emulation_active &&
870*11172SHaik.Aftandilian@Sun.COM (X_FAULT_TYPE(mmu_fsr) == FT_NEW_PRVACT) &&
871*11172SHaik.Aftandilian@Sun.COM simulate_rdtick(rp) == SIMU_SUCCESS) {
872*11172SHaik.Aftandilian@Sun.COM /* skip the successfully simulated instruction */
873*11172SHaik.Aftandilian@Sun.COM rp->r_pc = rp->r_npc;
874*11172SHaik.Aftandilian@Sun.COM rp->r_npc += 4;
875*11172SHaik.Aftandilian@Sun.COM goto out;
876*11172SHaik.Aftandilian@Sun.COM }
877*11172SHaik.Aftandilian@Sun.COM #endif
8780Sstevel@tonic-gate siginfo.si_signo = SIGILL;
8790Sstevel@tonic-gate siginfo.si_code = ILL_PRVOPC;
8800Sstevel@tonic-gate siginfo.si_addr = (caddr_t)rp->r_pc;
8810Sstevel@tonic-gate fault = FLTILL;
8820Sstevel@tonic-gate break;
8830Sstevel@tonic-gate
8840Sstevel@tonic-gate case T_UNIMP_INSTR: /* priv illegal instruction fault */
8850Sstevel@tonic-gate if (fpras_implemented) {
8860Sstevel@tonic-gate /*
8870Sstevel@tonic-gate * Call fpras_chktrap indicating that
8880Sstevel@tonic-gate * we've come from a trap handler and pass
8890Sstevel@tonic-gate * the regs. That function may choose to panic
8900Sstevel@tonic-gate * (in which case it won't return) or it may
8910Sstevel@tonic-gate * determine that a reboot is desired. In the
8920Sstevel@tonic-gate * latter case it must alter pc/npc to skip
8930Sstevel@tonic-gate * the illegal instruction and continue at
8940Sstevel@tonic-gate * a controlled address.
8950Sstevel@tonic-gate */
8960Sstevel@tonic-gate if (&fpras_chktrap) {
8975084Sjohnlev if (fpras_chktrap(rp))
8985084Sjohnlev goto cleanup;
8990Sstevel@tonic-gate }
9000Sstevel@tonic-gate }
9010Sstevel@tonic-gate #if defined(SF_ERRATA_23) || defined(SF_ERRATA_30) /* call ... illegal-insn */
9020Sstevel@tonic-gate instr = *(int *)rp->r_pc;
9030Sstevel@tonic-gate if ((instr & 0xc0000000) == 0x40000000) {
9040Sstevel@tonic-gate long pc;
9050Sstevel@tonic-gate
9060Sstevel@tonic-gate rp->r_o7 = (long long)rp->r_pc;
9070Sstevel@tonic-gate pc = rp->r_pc + ((instr & 0x3fffffff) << 2);
9080Sstevel@tonic-gate rp->r_pc = rp->r_npc;
9090Sstevel@tonic-gate rp->r_npc = pc;
9100Sstevel@tonic-gate ill_calls++;
9110Sstevel@tonic-gate goto cleanup;
9120Sstevel@tonic-gate }
9130Sstevel@tonic-gate #endif /* SF_ERRATA_23 || SF_ERRATA_30 */
9140Sstevel@tonic-gate /*
9150Sstevel@tonic-gate * It's not an fpras failure and it's not SF_ERRATA_23 - die
9160Sstevel@tonic-gate */
9170Sstevel@tonic-gate addr = (caddr_t)rp->r_pc;
9180Sstevel@tonic-gate (void) die(type, rp, addr, 0);
9190Sstevel@tonic-gate /*NOTREACHED*/
9200Sstevel@tonic-gate
9210Sstevel@tonic-gate case T_UNIMP_INSTR + T_USER: /* illegal instruction fault */
9220Sstevel@tonic-gate #if defined(SF_ERRATA_23) || defined(SF_ERRATA_30) /* call ... illegal-insn */
9230Sstevel@tonic-gate instr = fetch_user_instr((caddr_t)rp->r_pc);
9240Sstevel@tonic-gate if ((instr & 0xc0000000) == 0x40000000) {
9250Sstevel@tonic-gate long pc;
9260Sstevel@tonic-gate
9270Sstevel@tonic-gate rp->r_o7 = (long long)rp->r_pc;
9280Sstevel@tonic-gate pc = rp->r_pc + ((instr & 0x3fffffff) << 2);
9290Sstevel@tonic-gate rp->r_pc = rp->r_npc;
9300Sstevel@tonic-gate rp->r_npc = pc;
9310Sstevel@tonic-gate ill_calls++;
9320Sstevel@tonic-gate goto out;
9330Sstevel@tonic-gate }
9340Sstevel@tonic-gate #endif /* SF_ERRATA_23 || SF_ERRATA_30 */
9350Sstevel@tonic-gate if (tudebug)
9360Sstevel@tonic-gate showregs(type, rp, (caddr_t)0, 0);
9370Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
9380Sstevel@tonic-gate /*
9390Sstevel@tonic-gate * Try to simulate the instruction.
9400Sstevel@tonic-gate */
9410Sstevel@tonic-gate switch (simulate_unimp(rp, &badaddr)) {
9420Sstevel@tonic-gate case SIMU_RETRY:
9430Sstevel@tonic-gate goto out; /* regs are already set up */
9440Sstevel@tonic-gate /*NOTREACHED*/
9450Sstevel@tonic-gate
9460Sstevel@tonic-gate case SIMU_SUCCESS:
9470Sstevel@tonic-gate /* skip the successfully simulated instruction */
9480Sstevel@tonic-gate rp->r_pc = rp->r_npc;
9490Sstevel@tonic-gate rp->r_npc += 4;
9500Sstevel@tonic-gate goto out;
9510Sstevel@tonic-gate /*NOTREACHED*/
9520Sstevel@tonic-gate
9530Sstevel@tonic-gate case SIMU_FAULT:
9540Sstevel@tonic-gate siginfo.si_signo = SIGSEGV;
9550Sstevel@tonic-gate siginfo.si_code = SEGV_MAPERR;
9560Sstevel@tonic-gate siginfo.si_addr = badaddr;
9570Sstevel@tonic-gate fault = FLTBOUNDS;
9580Sstevel@tonic-gate break;
9590Sstevel@tonic-gate
9600Sstevel@tonic-gate case SIMU_DZERO:
9610Sstevel@tonic-gate siginfo.si_signo = SIGFPE;
9620Sstevel@tonic-gate siginfo.si_code = FPE_INTDIV;
9630Sstevel@tonic-gate siginfo.si_addr = (caddr_t)rp->r_pc;
9640Sstevel@tonic-gate fault = FLTIZDIV;
9650Sstevel@tonic-gate break;
9660Sstevel@tonic-gate
9670Sstevel@tonic-gate case SIMU_UNALIGN:
9680Sstevel@tonic-gate siginfo.si_signo = SIGBUS;
9690Sstevel@tonic-gate siginfo.si_code = BUS_ADRALN;
9700Sstevel@tonic-gate siginfo.si_addr = badaddr;
9710Sstevel@tonic-gate fault = FLTACCESS;
9720Sstevel@tonic-gate break;
9730Sstevel@tonic-gate
9740Sstevel@tonic-gate case SIMU_ILLEGAL:
9750Sstevel@tonic-gate default:
9760Sstevel@tonic-gate siginfo.si_signo = SIGILL;
9770Sstevel@tonic-gate op3 = (instr >> 19) & 0x3F;
9780Sstevel@tonic-gate if ((IS_FLOAT(instr) && (op3 == IOP_V8_STQFA) ||
9790Sstevel@tonic-gate (op3 == IOP_V8_STDFA)))
9800Sstevel@tonic-gate siginfo.si_code = ILL_ILLADR;
9810Sstevel@tonic-gate else
9820Sstevel@tonic-gate siginfo.si_code = ILL_ILLOPC;
9830Sstevel@tonic-gate siginfo.si_addr = (caddr_t)rp->r_pc;
9840Sstevel@tonic-gate fault = FLTILL;
9850Sstevel@tonic-gate break;
9860Sstevel@tonic-gate }
9870Sstevel@tonic-gate break;
9880Sstevel@tonic-gate
989518Swsm case T_UNIMP_LDD + T_USER:
990518Swsm case T_UNIMP_STD + T_USER:
991518Swsm if (tudebug)
992518Swsm showregs(type, rp, (caddr_t)0, 0);
993518Swsm switch (simulate_lddstd(rp, &badaddr)) {
994518Swsm case SIMU_SUCCESS:
995518Swsm /* skip the successfully simulated instruction */
996518Swsm rp->r_pc = rp->r_npc;
997518Swsm rp->r_npc += 4;
998518Swsm goto out;
999518Swsm /*NOTREACHED*/
1000518Swsm
1001518Swsm case SIMU_FAULT:
1002518Swsm if (nfload(rp, NULL))
1003518Swsm goto out;
1004518Swsm siginfo.si_signo = SIGSEGV;
1005518Swsm siginfo.si_code = SEGV_MAPERR;
1006518Swsm siginfo.si_addr = badaddr;
1007518Swsm fault = FLTBOUNDS;
1008518Swsm break;
1009518Swsm
1010518Swsm case SIMU_UNALIGN:
1011518Swsm if (nfload(rp, NULL))
1012518Swsm goto out;
1013518Swsm siginfo.si_signo = SIGBUS;
1014518Swsm siginfo.si_code = BUS_ADRALN;
1015518Swsm siginfo.si_addr = badaddr;
1016518Swsm fault = FLTACCESS;
1017518Swsm break;
1018518Swsm
1019518Swsm case SIMU_ILLEGAL:
1020518Swsm default:
1021518Swsm siginfo.si_signo = SIGILL;
1022518Swsm siginfo.si_code = ILL_ILLOPC;
1023518Swsm siginfo.si_addr = (caddr_t)rp->r_pc;
1024518Swsm fault = FLTILL;
1025518Swsm break;
1026518Swsm }
1027518Swsm break;
1028518Swsm
1029518Swsm case T_UNIMP_LDD:
1030518Swsm case T_UNIMP_STD:
1031518Swsm if (simulate_lddstd(rp, &badaddr) == SIMU_SUCCESS) {
1032518Swsm /* skip the successfully simulated instruction */
1033518Swsm rp->r_pc = rp->r_npc;
1034518Swsm rp->r_npc += 4;
1035518Swsm goto cleanup;
1036518Swsm /*NOTREACHED*/
1037518Swsm }
1038518Swsm /*
1039518Swsm * A third party driver executed an {LDD,STD,LDDA,STDA}
1040518Swsm * that we couldn't simulate.
1041518Swsm */
1042518Swsm if (nfload(rp, NULL))
1043518Swsm goto cleanup;
1044518Swsm
1045518Swsm if (curthread->t_lofault) {
1046518Swsm if (lodebug) {
1047518Swsm showregs(type, rp, addr, 0);
1048518Swsm traceback((caddr_t)rp->r_sp);
1049518Swsm }
1050518Swsm rp->r_g1 = EFAULT;
1051518Swsm rp->r_pc = curthread->t_lofault;
1052518Swsm rp->r_npc = rp->r_pc + 4;
1053518Swsm goto cleanup;
1054518Swsm }
1055518Swsm (void) die(type, rp, addr, 0);
1056518Swsm /*NOTREACHED*/
1057518Swsm
10580Sstevel@tonic-gate case T_IDIV0 + T_USER: /* integer divide by zero */
10590Sstevel@tonic-gate case T_DIV0 + T_USER: /* integer divide by zero */
10600Sstevel@tonic-gate if (tudebug && tudebugfpe)
10610Sstevel@tonic-gate showregs(type, rp, (caddr_t)0, 0);
10620Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
10630Sstevel@tonic-gate siginfo.si_signo = SIGFPE;
10640Sstevel@tonic-gate siginfo.si_code = FPE_INTDIV;
10650Sstevel@tonic-gate siginfo.si_addr = (caddr_t)rp->r_pc;
10660Sstevel@tonic-gate fault = FLTIZDIV;
10670Sstevel@tonic-gate break;
10680Sstevel@tonic-gate
10690Sstevel@tonic-gate case T_INT_OVERFLOW + T_USER: /* integer overflow */
10700Sstevel@tonic-gate if (tudebug && tudebugfpe)
10710Sstevel@tonic-gate showregs(type, rp, (caddr_t)0, 0);
10720Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
10730Sstevel@tonic-gate siginfo.si_signo = SIGFPE;
10740Sstevel@tonic-gate siginfo.si_code = FPE_INTOVF;
10750Sstevel@tonic-gate siginfo.si_addr = (caddr_t)rp->r_pc;
10760Sstevel@tonic-gate fault = FLTIOVF;
10770Sstevel@tonic-gate break;
10780Sstevel@tonic-gate
10790Sstevel@tonic-gate case T_BREAKPOINT + T_USER: /* breakpoint trap (t 1) */
10800Sstevel@tonic-gate if (tudebug && tudebugbpt)
10810Sstevel@tonic-gate showregs(type, rp, (caddr_t)0, 0);
10820Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
10830Sstevel@tonic-gate siginfo.si_signo = SIGTRAP;
10840Sstevel@tonic-gate siginfo.si_code = TRAP_BRKPT;
10850Sstevel@tonic-gate siginfo.si_addr = (caddr_t)rp->r_pc;
10860Sstevel@tonic-gate fault = FLTBPT;
10870Sstevel@tonic-gate break;
10880Sstevel@tonic-gate
10890Sstevel@tonic-gate case T_TAG_OVERFLOW + T_USER: /* tag overflow (taddcctv, tsubcctv) */
10900Sstevel@tonic-gate if (tudebug)
10910Sstevel@tonic-gate showregs(type, rp, (caddr_t)0, 0);
10920Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
10930Sstevel@tonic-gate siginfo.si_signo = SIGEMT;
10940Sstevel@tonic-gate siginfo.si_code = EMT_TAGOVF;
10950Sstevel@tonic-gate siginfo.si_addr = (caddr_t)rp->r_pc;
10960Sstevel@tonic-gate fault = FLTACCESS;
10970Sstevel@tonic-gate break;
10980Sstevel@tonic-gate
10990Sstevel@tonic-gate case T_FLUSH_PCB + T_USER: /* finish user window overflow */
11000Sstevel@tonic-gate case T_FLUSHW + T_USER: /* finish user window flush */
11010Sstevel@tonic-gate /*
11020Sstevel@tonic-gate * This trap is entered from sys_rtt in locore.s when,
11030Sstevel@tonic-gate * upon return to user is is found that there are user
11040Sstevel@tonic-gate * windows in pcb_wbuf. This happens because they could
11050Sstevel@tonic-gate * not be saved on the user stack, either because it
11060Sstevel@tonic-gate * wasn't resident or because it was misaligned.
11070Sstevel@tonic-gate */
11085084Sjohnlev {
11090Sstevel@tonic-gate int error;
11100Sstevel@tonic-gate caddr_t sp;
11110Sstevel@tonic-gate
11120Sstevel@tonic-gate error = flush_user_windows_to_stack(&sp);
11130Sstevel@tonic-gate /*
11140Sstevel@tonic-gate * Possible errors:
11150Sstevel@tonic-gate * error copying out
11160Sstevel@tonic-gate * unaligned stack pointer
11170Sstevel@tonic-gate * The first is given to us as the return value
11180Sstevel@tonic-gate * from flush_user_windows_to_stack(). The second
11190Sstevel@tonic-gate * results in residual windows in the pcb.
11200Sstevel@tonic-gate */
11210Sstevel@tonic-gate if (error != 0) {
11220Sstevel@tonic-gate /*
11230Sstevel@tonic-gate * EINTR comes from a signal during copyout;
11240Sstevel@tonic-gate * we should not post another signal.
11250Sstevel@tonic-gate */
11260Sstevel@tonic-gate if (error != EINTR) {
11270Sstevel@tonic-gate /*
11280Sstevel@tonic-gate * Zap the process with a SIGSEGV - process
11290Sstevel@tonic-gate * may be managing its own stack growth by
11300Sstevel@tonic-gate * taking SIGSEGVs on a different signal stack.
11310Sstevel@tonic-gate */
11320Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
11330Sstevel@tonic-gate siginfo.si_signo = SIGSEGV;
11340Sstevel@tonic-gate siginfo.si_code = SEGV_MAPERR;
11350Sstevel@tonic-gate siginfo.si_addr = sp;
11360Sstevel@tonic-gate fault = FLTBOUNDS;
11370Sstevel@tonic-gate }
11380Sstevel@tonic-gate break;
11390Sstevel@tonic-gate } else if (mpcb->mpcb_wbcnt) {
11400Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
11410Sstevel@tonic-gate siginfo.si_signo = SIGILL;
11420Sstevel@tonic-gate siginfo.si_code = ILL_BADSTK;
11430Sstevel@tonic-gate siginfo.si_addr = (caddr_t)rp->r_pc;
11440Sstevel@tonic-gate fault = FLTILL;
11450Sstevel@tonic-gate break;
11460Sstevel@tonic-gate }
11475084Sjohnlev }
11480Sstevel@tonic-gate
11490Sstevel@tonic-gate /*
11500Sstevel@tonic-gate * T_FLUSHW is used when handling a ta 0x3 -- the old flush
11510Sstevel@tonic-gate * window trap -- which is implemented by executing the
11520Sstevel@tonic-gate * flushw instruction. The flushw can trap if any of the
11530Sstevel@tonic-gate * stack pages are not writable for whatever reason. In this
11540Sstevel@tonic-gate * case only, we advance the pc to the next instruction so
11550Sstevel@tonic-gate * that the user thread doesn't needlessly execute the trap
11560Sstevel@tonic-gate * again. Normally this wouldn't be a problem -- we'll
11570Sstevel@tonic-gate * usually only end up here if this is the first touch to a
11580Sstevel@tonic-gate * stack page -- since the second execution won't trap, but
11590Sstevel@tonic-gate * if there's a watchpoint on the stack page the user thread
11600Sstevel@tonic-gate * would spin, continuously executing the trap instruction.
11610Sstevel@tonic-gate */
11620Sstevel@tonic-gate if (type == T_FLUSHW + T_USER) {
11630Sstevel@tonic-gate rp->r_pc = rp->r_npc;
11640Sstevel@tonic-gate rp->r_npc += 4;
11650Sstevel@tonic-gate }
11660Sstevel@tonic-gate goto out;
11670Sstevel@tonic-gate
11680Sstevel@tonic-gate case T_AST + T_USER: /* profiling or resched pseudo trap */
11690Sstevel@tonic-gate if (lwp->lwp_pcb.pcb_flags & CPC_OVERFLOW) {
11700Sstevel@tonic-gate lwp->lwp_pcb.pcb_flags &= ~CPC_OVERFLOW;
11710Sstevel@tonic-gate if (kcpc_overflow_ast()) {
11720Sstevel@tonic-gate /*
11730Sstevel@tonic-gate * Signal performance counter overflow
11740Sstevel@tonic-gate */
11750Sstevel@tonic-gate if (tudebug)
11760Sstevel@tonic-gate showregs(type, rp, (caddr_t)0, 0);
11770Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
11780Sstevel@tonic-gate siginfo.si_signo = SIGEMT;
11790Sstevel@tonic-gate siginfo.si_code = EMT_CPCOVF;
11800Sstevel@tonic-gate siginfo.si_addr = (caddr_t)rp->r_pc;
11810Sstevel@tonic-gate /* for trap_cleanup(), below */
11820Sstevel@tonic-gate oldpc = rp->r_pc - 4;
11830Sstevel@tonic-gate fault = FLTCPCOVF;
11840Sstevel@tonic-gate }
11850Sstevel@tonic-gate }
11860Sstevel@tonic-gate
11870Sstevel@tonic-gate /*
11880Sstevel@tonic-gate * The CPC_OVERFLOW check above may already have populated
11890Sstevel@tonic-gate * siginfo and set fault, so the checks below must not
11900Sstevel@tonic-gate * touch these and the functions they call must use
11910Sstevel@tonic-gate * trapsig() directly.
11920Sstevel@tonic-gate */
11930Sstevel@tonic-gate
11940Sstevel@tonic-gate if (lwp->lwp_pcb.pcb_flags & ASYNC_HWERR) {
11950Sstevel@tonic-gate lwp->lwp_pcb.pcb_flags &= ~ASYNC_HWERR;
11960Sstevel@tonic-gate trap_async_hwerr();
11970Sstevel@tonic-gate }
11980Sstevel@tonic-gate
11990Sstevel@tonic-gate if (lwp->lwp_pcb.pcb_flags & ASYNC_BERR) {
12000Sstevel@tonic-gate lwp->lwp_pcb.pcb_flags &= ~ASYNC_BERR;
12010Sstevel@tonic-gate trap_async_berr_bto(ASYNC_BERR, rp);
12020Sstevel@tonic-gate }
12030Sstevel@tonic-gate
12040Sstevel@tonic-gate if (lwp->lwp_pcb.pcb_flags & ASYNC_BTO) {
12050Sstevel@tonic-gate lwp->lwp_pcb.pcb_flags &= ~ASYNC_BTO;
12060Sstevel@tonic-gate trap_async_berr_bto(ASYNC_BTO, rp);
12070Sstevel@tonic-gate }
12080Sstevel@tonic-gate
12090Sstevel@tonic-gate break;
12100Sstevel@tonic-gate }
12110Sstevel@tonic-gate
12123506Saf if (fault) {
12133506Saf /* We took a fault so abort single step. */
12143506Saf lwp->lwp_pcb.pcb_flags &= ~(NORMAL_STEP|WATCH_STEP);
12153506Saf }
12160Sstevel@tonic-gate trap_cleanup(rp, fault, &siginfo, oldpc == rp->r_pc);
12170Sstevel@tonic-gate
12180Sstevel@tonic-gate out: /* We can't get here from a system trap */
12190Sstevel@tonic-gate ASSERT(type & T_USER);
12200Sstevel@tonic-gate trap_rtt();
12210Sstevel@tonic-gate (void) new_mstate(curthread, mstate);
12220Sstevel@tonic-gate /* Kernel probe */
12230Sstevel@tonic-gate TNF_PROBE_1(thread_state, "thread", /* CSTYLED */,
12240Sstevel@tonic-gate tnf_microstate, state, LMS_USER);
12250Sstevel@tonic-gate
12260Sstevel@tonic-gate TRACE_0(TR_FAC_TRAP, TR_C_TRAP_HANDLER_EXIT, "C_trap_handler_exit");
12270Sstevel@tonic-gate return;
12280Sstevel@tonic-gate
12290Sstevel@tonic-gate cleanup: /* system traps end up here */
12300Sstevel@tonic-gate ASSERT(!(type & T_USER));
12310Sstevel@tonic-gate
12320Sstevel@tonic-gate TRACE_0(TR_FAC_TRAP, TR_C_TRAP_HANDLER_EXIT, "C_trap_handler_exit");
12330Sstevel@tonic-gate }
12340Sstevel@tonic-gate
12350Sstevel@tonic-gate void
trap_cleanup(struct regs * rp,uint_t fault,k_siginfo_t * sip,int restartable)12360Sstevel@tonic-gate trap_cleanup(
12370Sstevel@tonic-gate struct regs *rp,
12380Sstevel@tonic-gate uint_t fault,
12390Sstevel@tonic-gate k_siginfo_t *sip,
12400Sstevel@tonic-gate int restartable)
12410Sstevel@tonic-gate {
12420Sstevel@tonic-gate extern void aio_cleanup();
12430Sstevel@tonic-gate proc_t *p = ttoproc(curthread);
12440Sstevel@tonic-gate klwp_id_t lwp = ttolwp(curthread);
12450Sstevel@tonic-gate
12460Sstevel@tonic-gate if (fault) {
12470Sstevel@tonic-gate /*
12480Sstevel@tonic-gate * Remember the fault and fault address
12490Sstevel@tonic-gate * for real-time (SIGPROF) profiling.
12500Sstevel@tonic-gate */
12510Sstevel@tonic-gate lwp->lwp_lastfault = fault;
12520Sstevel@tonic-gate lwp->lwp_lastfaddr = sip->si_addr;
12530Sstevel@tonic-gate
12540Sstevel@tonic-gate DTRACE_PROC2(fault, int, fault, ksiginfo_t *, sip);
12550Sstevel@tonic-gate
12560Sstevel@tonic-gate /*
12570Sstevel@tonic-gate * If a debugger has declared this fault to be an
12580Sstevel@tonic-gate * event of interest, stop the lwp. Otherwise just
12590Sstevel@tonic-gate * deliver the associated signal.
12600Sstevel@tonic-gate */
12610Sstevel@tonic-gate if (sip->si_signo != SIGKILL &&
12620Sstevel@tonic-gate prismember(&p->p_fltmask, fault) &&
12630Sstevel@tonic-gate stop_on_fault(fault, sip) == 0)
12640Sstevel@tonic-gate sip->si_signo = 0;
12650Sstevel@tonic-gate }
12660Sstevel@tonic-gate
12670Sstevel@tonic-gate if (sip->si_signo)
12680Sstevel@tonic-gate trapsig(sip, restartable);
12690Sstevel@tonic-gate
12700Sstevel@tonic-gate if (lwp->lwp_oweupc)
12710Sstevel@tonic-gate profil_tick(rp->r_pc);
12720Sstevel@tonic-gate
12730Sstevel@tonic-gate if (curthread->t_astflag | curthread->t_sig_check) {
12740Sstevel@tonic-gate /*
12750Sstevel@tonic-gate * Turn off the AST flag before checking all the conditions that
12760Sstevel@tonic-gate * may have caused an AST. This flag is on whenever a signal or
12770Sstevel@tonic-gate * unusual condition should be handled after the next trap or
12780Sstevel@tonic-gate * syscall.
12790Sstevel@tonic-gate */
12800Sstevel@tonic-gate astoff(curthread);
12810Sstevel@tonic-gate curthread->t_sig_check = 0;
12820Sstevel@tonic-gate
12831972Sdv142724 /*
12841972Sdv142724 * The following check is legal for the following reasons:
12851972Sdv142724 * 1) The thread we are checking, is ourselves, so there is
12861972Sdv142724 * no way the proc can go away.
12871972Sdv142724 * 2) The only time we need to be protected by the
12881972Sdv142724 * lock is if the binding is changed.
12891972Sdv142724 *
12901972Sdv142724 * Note we will still take the lock and check the binding
12911972Sdv142724 * if the condition was true without the lock held. This
12921972Sdv142724 * prevents lock contention among threads owned by the
12931972Sdv142724 * same proc.
12941972Sdv142724 */
12951972Sdv142724
12960Sstevel@tonic-gate if (curthread->t_proc_flag & TP_CHANGEBIND) {
12971972Sdv142724 mutex_enter(&p->p_lock);
12981972Sdv142724 if (curthread->t_proc_flag & TP_CHANGEBIND) {
12991972Sdv142724 timer_lwpbind();
13001972Sdv142724 curthread->t_proc_flag &= ~TP_CHANGEBIND;
13011972Sdv142724 }
13021972Sdv142724 mutex_exit(&p->p_lock);
13030Sstevel@tonic-gate }
13040Sstevel@tonic-gate
13050Sstevel@tonic-gate /*
13060Sstevel@tonic-gate * for kaio requests that are on the per-process poll queue,
13070Sstevel@tonic-gate * aiop->aio_pollq, they're AIO_POLL bit is set, the kernel
13080Sstevel@tonic-gate * should copyout their result_t to user memory. by copying
13090Sstevel@tonic-gate * out the result_t, the user can poll on memory waiting
13100Sstevel@tonic-gate * for the kaio request to complete.
13110Sstevel@tonic-gate */
13120Sstevel@tonic-gate if (p->p_aio)
13130Sstevel@tonic-gate aio_cleanup(0);
13140Sstevel@tonic-gate
13150Sstevel@tonic-gate /*
13160Sstevel@tonic-gate * If this LWP was asked to hold, call holdlwp(), which will
13170Sstevel@tonic-gate * stop. holdlwps() sets this up and calls pokelwps() which
13180Sstevel@tonic-gate * sets the AST flag.
13190Sstevel@tonic-gate *
13200Sstevel@tonic-gate * Also check TP_EXITLWP, since this is used by fresh new LWPs
13210Sstevel@tonic-gate * through lwp_rtt(). That flag is set if the lwp_create(2)
13220Sstevel@tonic-gate * syscall failed after creating the LWP.
13230Sstevel@tonic-gate */
13240Sstevel@tonic-gate if (ISHOLD(p))
13250Sstevel@tonic-gate holdlwp();
13260Sstevel@tonic-gate
13270Sstevel@tonic-gate /*
13280Sstevel@tonic-gate * All code that sets signals and makes ISSIG evaluate true must
13290Sstevel@tonic-gate * set t_astflag afterwards.
13300Sstevel@tonic-gate */
13310Sstevel@tonic-gate if (ISSIG_PENDING(curthread, lwp, p)) {
13320Sstevel@tonic-gate if (issig(FORREAL))
13330Sstevel@tonic-gate psig();
13340Sstevel@tonic-gate curthread->t_sig_check = 1;
13350Sstevel@tonic-gate }
13360Sstevel@tonic-gate
13370Sstevel@tonic-gate if (curthread->t_rprof != NULL) {
13389870SRoger.Faulkner@Sun.COM realsigprof(0, 0, 0);
13390Sstevel@tonic-gate curthread->t_sig_check = 1;
13400Sstevel@tonic-gate }
13410Sstevel@tonic-gate }
13420Sstevel@tonic-gate }
13430Sstevel@tonic-gate
13440Sstevel@tonic-gate /*
13450Sstevel@tonic-gate * Called from fp_traps when a floating point trap occurs.
13460Sstevel@tonic-gate * Note that the T_DATA_EXCEPTION case does not use X_FAULT_TYPE(mmu_fsr),
13470Sstevel@tonic-gate * because mmu_fsr (now changed to code) is always 0.
13480Sstevel@tonic-gate * Note that the T_UNIMP_INSTR case does not call simulate_unimp(),
13490Sstevel@tonic-gate * because the simulator only simulates multiply and divide instructions,
13500Sstevel@tonic-gate * which would not cause floating point traps in the first place.
13510Sstevel@tonic-gate * XXX - Supervisor mode floating point traps?
13520Sstevel@tonic-gate */
13530Sstevel@tonic-gate void
fpu_trap(struct regs * rp,caddr_t addr,uint32_t type,uint32_t code)13540Sstevel@tonic-gate fpu_trap(struct regs *rp, caddr_t addr, uint32_t type, uint32_t code)
13550Sstevel@tonic-gate {
13560Sstevel@tonic-gate proc_t *p = ttoproc(curthread);
13570Sstevel@tonic-gate klwp_id_t lwp = ttolwp(curthread);
13580Sstevel@tonic-gate k_siginfo_t siginfo;
13590Sstevel@tonic-gate uint_t op3, fault = 0;
13600Sstevel@tonic-gate int mstate;
13610Sstevel@tonic-gate char *badaddr;
13620Sstevel@tonic-gate kfpu_t *fp;
13630Sstevel@tonic-gate struct fpq *pfpq;
13640Sstevel@tonic-gate uint32_t inst;
13650Sstevel@tonic-gate utrap_handler_t *utrapp;
13660Sstevel@tonic-gate
13670Sstevel@tonic-gate CPU_STATS_ADDQ(CPU, sys, trap, 1);
13680Sstevel@tonic-gate
13690Sstevel@tonic-gate ASSERT(curthread->t_schedflag & TS_DONT_SWAP);
13700Sstevel@tonic-gate
13710Sstevel@tonic-gate if (USERMODE(rp->r_tstate)) {
13720Sstevel@tonic-gate /*
13730Sstevel@tonic-gate * Set lwp_state before trying to acquire any
13740Sstevel@tonic-gate * adaptive lock
13750Sstevel@tonic-gate */
13760Sstevel@tonic-gate ASSERT(lwp != NULL);
13770Sstevel@tonic-gate lwp->lwp_state = LWP_SYS;
13780Sstevel@tonic-gate /*
13790Sstevel@tonic-gate * Set up the current cred to use during this trap. u_cred
13800Sstevel@tonic-gate * no longer exists. t_cred is used instead.
13810Sstevel@tonic-gate * The current process credential applies to the thread for
13820Sstevel@tonic-gate * the entire trap. If trapping from the kernel, this
13830Sstevel@tonic-gate * should already be set up.
13840Sstevel@tonic-gate */
13850Sstevel@tonic-gate if (curthread->t_cred != p->p_cred) {
13860Sstevel@tonic-gate cred_t *oldcred = curthread->t_cred;
13870Sstevel@tonic-gate /*
13880Sstevel@tonic-gate * DTrace accesses t_cred in probe context. t_cred
13890Sstevel@tonic-gate * must always be either NULL, or point to a valid,
13900Sstevel@tonic-gate * allocated cred structure.
13910Sstevel@tonic-gate */
13920Sstevel@tonic-gate curthread->t_cred = crgetcred();
13930Sstevel@tonic-gate crfree(oldcred);
13940Sstevel@tonic-gate }
13950Sstevel@tonic-gate ASSERT(lwp->lwp_regs == rp);
13960Sstevel@tonic-gate mstate = new_mstate(curthread, LMS_TRAP);
13970Sstevel@tonic-gate siginfo.si_signo = 0;
13980Sstevel@tonic-gate type |= T_USER;
13990Sstevel@tonic-gate }
14000Sstevel@tonic-gate
14010Sstevel@tonic-gate TRACE_1(TR_FAC_TRAP, TR_C_TRAP_HANDLER_ENTER,
14025084Sjohnlev "C_fpu_trap_handler_enter:type %x", type);
14030Sstevel@tonic-gate
14040Sstevel@tonic-gate if (tudebug && tudebugfpe)
14050Sstevel@tonic-gate showregs(type, rp, addr, 0);
14060Sstevel@tonic-gate
14070Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
14080Sstevel@tonic-gate siginfo.si_code = code;
14090Sstevel@tonic-gate siginfo.si_addr = addr;
14100Sstevel@tonic-gate
14110Sstevel@tonic-gate switch (type) {
14120Sstevel@tonic-gate
14130Sstevel@tonic-gate case T_FP_EXCEPTION_IEEE + T_USER: /* FPU arithmetic exception */
14140Sstevel@tonic-gate /*
14150Sstevel@tonic-gate * FPU arithmetic exception - fake up a fpq if we
14160Sstevel@tonic-gate * came here directly from _fp_ieee_exception,
14170Sstevel@tonic-gate * which is indicated by a zero fpu_qcnt.
14180Sstevel@tonic-gate */
14190Sstevel@tonic-gate fp = lwptofpu(curthread->t_lwp);
14200Sstevel@tonic-gate utrapp = curthread->t_procp->p_utraps;
14210Sstevel@tonic-gate if (fp->fpu_qcnt == 0) {
14220Sstevel@tonic-gate inst = fetch_user_instr((caddr_t)rp->r_pc);
14230Sstevel@tonic-gate lwp->lwp_state = LWP_SYS;
14240Sstevel@tonic-gate pfpq = &fp->fpu_q->FQu.fpq;
14250Sstevel@tonic-gate pfpq->fpq_addr = (uint32_t *)rp->r_pc;
14260Sstevel@tonic-gate pfpq->fpq_instr = inst;
14270Sstevel@tonic-gate fp->fpu_qcnt = 1;
14280Sstevel@tonic-gate fp->fpu_q_entrysize = sizeof (struct fpq);
14290Sstevel@tonic-gate #ifdef SF_V9_TABLE_28
14300Sstevel@tonic-gate /*
14310Sstevel@tonic-gate * Spitfire and blackbird followed the SPARC V9 manual
14320Sstevel@tonic-gate * paragraph 3 of section 5.1.7.9 FSR_current_exception
14330Sstevel@tonic-gate * (cexc) for setting fsr.cexc bits on underflow and
14340Sstevel@tonic-gate * overflow traps when the fsr.tem.inexact bit is set,
14350Sstevel@tonic-gate * instead of following Table 28. Bugid 1263234.
14360Sstevel@tonic-gate */
14370Sstevel@tonic-gate {
14380Sstevel@tonic-gate extern int spitfire_bb_fsr_bug;
14390Sstevel@tonic-gate
14400Sstevel@tonic-gate if (spitfire_bb_fsr_bug &&
14410Sstevel@tonic-gate (fp->fpu_fsr & FSR_TEM_NX)) {
14420Sstevel@tonic-gate if (((fp->fpu_fsr & FSR_TEM_OF) == 0) &&
14430Sstevel@tonic-gate (fp->fpu_fsr & FSR_CEXC_OF)) {
14440Sstevel@tonic-gate fp->fpu_fsr &= ~FSR_CEXC_OF;
14450Sstevel@tonic-gate fp->fpu_fsr |= FSR_CEXC_NX;
14460Sstevel@tonic-gate _fp_write_pfsr(&fp->fpu_fsr);
14470Sstevel@tonic-gate siginfo.si_code = FPE_FLTRES;
14480Sstevel@tonic-gate }
14490Sstevel@tonic-gate if (((fp->fpu_fsr & FSR_TEM_UF) == 0) &&
14500Sstevel@tonic-gate (fp->fpu_fsr & FSR_CEXC_UF)) {
14510Sstevel@tonic-gate fp->fpu_fsr &= ~FSR_CEXC_UF;
14520Sstevel@tonic-gate fp->fpu_fsr |= FSR_CEXC_NX;
14530Sstevel@tonic-gate _fp_write_pfsr(&fp->fpu_fsr);
14540Sstevel@tonic-gate siginfo.si_code = FPE_FLTRES;
14550Sstevel@tonic-gate }
14560Sstevel@tonic-gate }
14570Sstevel@tonic-gate }
14580Sstevel@tonic-gate #endif /* SF_V9_TABLE_28 */
14590Sstevel@tonic-gate rp->r_pc = rp->r_npc;
14600Sstevel@tonic-gate rp->r_npc += 4;
14610Sstevel@tonic-gate } else if (utrapp && utrapp[UT_FP_EXCEPTION_IEEE_754]) {
14620Sstevel@tonic-gate /*
14630Sstevel@tonic-gate * The user had a trap handler installed. Jump to
14640Sstevel@tonic-gate * the trap handler instead of signalling the process.
14650Sstevel@tonic-gate */
14660Sstevel@tonic-gate rp->r_pc = (long)utrapp[UT_FP_EXCEPTION_IEEE_754];
14670Sstevel@tonic-gate rp->r_npc = rp->r_pc + 4;
14680Sstevel@tonic-gate break;
14690Sstevel@tonic-gate }
14700Sstevel@tonic-gate siginfo.si_signo = SIGFPE;
14710Sstevel@tonic-gate fault = FLTFPE;
14720Sstevel@tonic-gate break;
14730Sstevel@tonic-gate
14740Sstevel@tonic-gate case T_DATA_EXCEPTION + T_USER: /* user data access exception */
14750Sstevel@tonic-gate siginfo.si_signo = SIGSEGV;
14760Sstevel@tonic-gate fault = FLTBOUNDS;
14770Sstevel@tonic-gate break;
14780Sstevel@tonic-gate
14790Sstevel@tonic-gate case T_LDDF_ALIGN + T_USER: /* 64 bit user lddfa alignment error */
14800Sstevel@tonic-gate case T_STDF_ALIGN + T_USER: /* 64 bit user stdfa alignment error */
14810Sstevel@tonic-gate alignfaults++;
14820Sstevel@tonic-gate lwp->lwp_state = LWP_SYS;
14832153Sjfrank if (&vis1_partial_support != NULL) {
14842153Sjfrank bzero(&siginfo, sizeof (siginfo));
14852153Sjfrank if (vis1_partial_support(rp,
14862153Sjfrank &siginfo, &fault) == 0)
14872153Sjfrank goto out;
14882153Sjfrank }
14890Sstevel@tonic-gate if (do_unaligned(rp, &badaddr) == SIMU_SUCCESS) {
14900Sstevel@tonic-gate rp->r_pc = rp->r_npc;
14910Sstevel@tonic-gate rp->r_npc += 4;
14920Sstevel@tonic-gate goto out;
14930Sstevel@tonic-gate }
14940Sstevel@tonic-gate fp = lwptofpu(curthread->t_lwp);
14950Sstevel@tonic-gate fp->fpu_qcnt = 0;
14960Sstevel@tonic-gate siginfo.si_signo = SIGSEGV;
14970Sstevel@tonic-gate siginfo.si_code = SEGV_MAPERR;
14980Sstevel@tonic-gate siginfo.si_addr = badaddr;
14990Sstevel@tonic-gate fault = FLTBOUNDS;
15000Sstevel@tonic-gate break;
15010Sstevel@tonic-gate
15020Sstevel@tonic-gate case T_ALIGNMENT + T_USER: /* user alignment error */
15030Sstevel@tonic-gate /*
15040Sstevel@tonic-gate * If the user has to do unaligned references
15050Sstevel@tonic-gate * the ugly stuff gets done here.
15060Sstevel@tonic-gate * Only handles vanilla loads and stores.
15070Sstevel@tonic-gate */
15080Sstevel@tonic-gate alignfaults++;
15090Sstevel@tonic-gate if (p->p_fixalignment) {
15100Sstevel@tonic-gate if (do_unaligned(rp, &badaddr) == SIMU_SUCCESS) {
15110Sstevel@tonic-gate rp->r_pc = rp->r_npc;
15120Sstevel@tonic-gate rp->r_npc += 4;
15130Sstevel@tonic-gate goto out;
15140Sstevel@tonic-gate }
15150Sstevel@tonic-gate siginfo.si_signo = SIGSEGV;
15160Sstevel@tonic-gate siginfo.si_code = SEGV_MAPERR;
15170Sstevel@tonic-gate siginfo.si_addr = badaddr;
15180Sstevel@tonic-gate fault = FLTBOUNDS;
15190Sstevel@tonic-gate } else {
15200Sstevel@tonic-gate siginfo.si_signo = SIGBUS;
15210Sstevel@tonic-gate siginfo.si_code = BUS_ADRALN;
15220Sstevel@tonic-gate if (rp->r_pc & 3) { /* offending address, if pc */
15230Sstevel@tonic-gate siginfo.si_addr = (caddr_t)rp->r_pc;
15240Sstevel@tonic-gate } else {
15250Sstevel@tonic-gate if (calc_memaddr(rp, &badaddr) == SIMU_UNALIGN)
15260Sstevel@tonic-gate siginfo.si_addr = badaddr;
15270Sstevel@tonic-gate else
15280Sstevel@tonic-gate siginfo.si_addr = (caddr_t)rp->r_pc;
15290Sstevel@tonic-gate }
15300Sstevel@tonic-gate fault = FLTACCESS;
15310Sstevel@tonic-gate }
15320Sstevel@tonic-gate break;
15330Sstevel@tonic-gate
15340Sstevel@tonic-gate case T_UNIMP_INSTR + T_USER: /* illegal instruction fault */
15350Sstevel@tonic-gate siginfo.si_signo = SIGILL;
15360Sstevel@tonic-gate inst = fetch_user_instr((caddr_t)rp->r_pc);
15370Sstevel@tonic-gate op3 = (inst >> 19) & 0x3F;
15380Sstevel@tonic-gate if ((op3 == IOP_V8_STQFA) || (op3 == IOP_V8_STDFA))
15390Sstevel@tonic-gate siginfo.si_code = ILL_ILLADR;
15400Sstevel@tonic-gate else
15410Sstevel@tonic-gate siginfo.si_code = ILL_ILLTRP;
15420Sstevel@tonic-gate fault = FLTILL;
15430Sstevel@tonic-gate break;
15440Sstevel@tonic-gate
15450Sstevel@tonic-gate default:
15460Sstevel@tonic-gate (void) die(type, rp, addr, 0);
15470Sstevel@tonic-gate /*NOTREACHED*/
15480Sstevel@tonic-gate }
15490Sstevel@tonic-gate
15500Sstevel@tonic-gate /*
15510Sstevel@tonic-gate * We can't get here from a system trap
15520Sstevel@tonic-gate * Never restart any instruction which got here from an fp trap.
15530Sstevel@tonic-gate */
15540Sstevel@tonic-gate ASSERT(type & T_USER);
15550Sstevel@tonic-gate
15560Sstevel@tonic-gate trap_cleanup(rp, fault, &siginfo, 0);
15570Sstevel@tonic-gate out:
15580Sstevel@tonic-gate trap_rtt();
15590Sstevel@tonic-gate (void) new_mstate(curthread, mstate);
15600Sstevel@tonic-gate }
15610Sstevel@tonic-gate
15620Sstevel@tonic-gate void
trap_rtt(void)15630Sstevel@tonic-gate trap_rtt(void)
15640Sstevel@tonic-gate {
15650Sstevel@tonic-gate klwp_id_t lwp = ttolwp(curthread);
15660Sstevel@tonic-gate
15670Sstevel@tonic-gate /*
15680Sstevel@tonic-gate * Restore register window if a debugger modified it.
15690Sstevel@tonic-gate * Set up to perform a single-step if a debugger requested it.
15700Sstevel@tonic-gate */
15710Sstevel@tonic-gate if (lwp->lwp_pcb.pcb_xregstat != XREGNONE)
15720Sstevel@tonic-gate xregrestore(lwp, 0);
15730Sstevel@tonic-gate
15740Sstevel@tonic-gate /*
15750Sstevel@tonic-gate * Set state to LWP_USER here so preempt won't give us a kernel
15760Sstevel@tonic-gate * priority if it occurs after this point. Call CL_TRAPRET() to
15770Sstevel@tonic-gate * restore the user-level priority.
15780Sstevel@tonic-gate *
15790Sstevel@tonic-gate * It is important that no locks (other than spinlocks) be entered
15800Sstevel@tonic-gate * after this point before returning to user mode (unless lwp_state
15810Sstevel@tonic-gate * is set back to LWP_SYS).
15820Sstevel@tonic-gate */
15830Sstevel@tonic-gate lwp->lwp_state = LWP_USER;
15840Sstevel@tonic-gate if (curthread->t_trapret) {
15850Sstevel@tonic-gate curthread->t_trapret = 0;
15860Sstevel@tonic-gate thread_lock(curthread);
15870Sstevel@tonic-gate CL_TRAPRET(curthread);
15880Sstevel@tonic-gate thread_unlock(curthread);
15890Sstevel@tonic-gate }
15903792Sakolb if (CPU->cpu_runrun || curthread->t_schedflag & TS_ANYWAITQ)
15910Sstevel@tonic-gate preempt();
159210230SRoger.Faulkner@Sun.COM prunstop();
15930Sstevel@tonic-gate if (lwp->lwp_pcb.pcb_step != STEP_NONE)
15940Sstevel@tonic-gate prdostep();
15950Sstevel@tonic-gate
15960Sstevel@tonic-gate TRACE_0(TR_FAC_TRAP, TR_C_TRAP_HANDLER_EXIT, "C_trap_handler_exit");
15970Sstevel@tonic-gate }
15980Sstevel@tonic-gate
15990Sstevel@tonic-gate #define IS_LDASI(o) \
16000Sstevel@tonic-gate ((o) == (uint32_t)0xC0C00000 || (o) == (uint32_t)0xC0800000 || \
16010Sstevel@tonic-gate (o) == (uint32_t)0xC1800000)
16020Sstevel@tonic-gate #define IS_IMM_ASI(i) (((i) & 0x2000) == 0)
16030Sstevel@tonic-gate #define IS_ASINF(a) (((a) & 0xF6) == 0x82)
16040Sstevel@tonic-gate #define IS_LDDA(i) (((i) & 0xC1F80000) == 0xC0980000)
16050Sstevel@tonic-gate
16060Sstevel@tonic-gate static int
nfload(struct regs * rp,int * instrp)16070Sstevel@tonic-gate nfload(struct regs *rp, int *instrp)
16080Sstevel@tonic-gate {
16090Sstevel@tonic-gate uint_t instr, asi, op3, rd;
16100Sstevel@tonic-gate size_t len;
16110Sstevel@tonic-gate struct as *as;
16120Sstevel@tonic-gate caddr_t addr;
16130Sstevel@tonic-gate FPU_DREGS_TYPE zero;
16140Sstevel@tonic-gate extern int segnf_create();
16150Sstevel@tonic-gate
16160Sstevel@tonic-gate if (USERMODE(rp->r_tstate))
16170Sstevel@tonic-gate instr = fetch_user_instr((caddr_t)rp->r_pc);
16180Sstevel@tonic-gate else
16190Sstevel@tonic-gate instr = *(int *)rp->r_pc;
16200Sstevel@tonic-gate
16210Sstevel@tonic-gate if (instrp)
16220Sstevel@tonic-gate *instrp = instr;
16230Sstevel@tonic-gate
16240Sstevel@tonic-gate op3 = (uint_t)(instr & 0xC1E00000);
16250Sstevel@tonic-gate if (!IS_LDASI(op3))
16260Sstevel@tonic-gate return (0);
16270Sstevel@tonic-gate if (IS_IMM_ASI(instr))
16280Sstevel@tonic-gate asi = (instr & 0x1FE0) >> 5;
16290Sstevel@tonic-gate else
16300Sstevel@tonic-gate asi = (uint_t)((rp->r_tstate >> TSTATE_ASI_SHIFT) &
16310Sstevel@tonic-gate TSTATE_ASI_MASK);
16320Sstevel@tonic-gate if (!IS_ASINF(asi))
16330Sstevel@tonic-gate return (0);
16340Sstevel@tonic-gate if (calc_memaddr(rp, &addr) == SIMU_SUCCESS) {
16350Sstevel@tonic-gate len = 1;
16360Sstevel@tonic-gate as = USERMODE(rp->r_tstate) ? ttoproc(curthread)->p_as : &kas;
16370Sstevel@tonic-gate as_rangelock(as);
16380Sstevel@tonic-gate if (as_gap(as, len, &addr, &len, 0, addr) == 0)
16390Sstevel@tonic-gate (void) as_map(as, addr, len, segnf_create, NULL);
16400Sstevel@tonic-gate as_rangeunlock(as);
16410Sstevel@tonic-gate }
16420Sstevel@tonic-gate zero = 0;
16430Sstevel@tonic-gate rd = (instr >> 25) & 0x1f;
16440Sstevel@tonic-gate if (IS_FLOAT(instr)) {
16450Sstevel@tonic-gate uint_t dbflg = ((instr >> 19) & 3) == 3;
16460Sstevel@tonic-gate
16470Sstevel@tonic-gate if (dbflg) { /* clever v9 reg encoding */
16480Sstevel@tonic-gate if (rd & 1)
16490Sstevel@tonic-gate rd = (rd & 0x1e) | 0x20;
16500Sstevel@tonic-gate rd >>= 1;
16510Sstevel@tonic-gate }
16520Sstevel@tonic-gate if (fpu_exists) {
16530Sstevel@tonic-gate if (!(_fp_read_fprs() & FPRS_FEF))
16540Sstevel@tonic-gate fp_enable();
16550Sstevel@tonic-gate
16560Sstevel@tonic-gate if (dbflg)
16570Sstevel@tonic-gate _fp_write_pdreg(&zero, rd);
16580Sstevel@tonic-gate else
16590Sstevel@tonic-gate _fp_write_pfreg((uint_t *)&zero, rd);
16600Sstevel@tonic-gate } else {
16610Sstevel@tonic-gate kfpu_t *fp = lwptofpu(curthread->t_lwp);
16620Sstevel@tonic-gate
16630Sstevel@tonic-gate if (!fp->fpu_en)
16640Sstevel@tonic-gate fp_enable();
16650Sstevel@tonic-gate
16660Sstevel@tonic-gate if (dbflg)
16670Sstevel@tonic-gate fp->fpu_fr.fpu_dregs[rd] = zero;
16680Sstevel@tonic-gate else
16690Sstevel@tonic-gate fp->fpu_fr.fpu_regs[rd] = 0;
16700Sstevel@tonic-gate }
16710Sstevel@tonic-gate } else {
16720Sstevel@tonic-gate (void) putreg(&zero, rp, rd, &addr);
16730Sstevel@tonic-gate if (IS_LDDA(instr))
16740Sstevel@tonic-gate (void) putreg(&zero, rp, rd + 1, &addr);
16750Sstevel@tonic-gate }
16760Sstevel@tonic-gate rp->r_pc = rp->r_npc;
16770Sstevel@tonic-gate rp->r_npc += 4;
16780Sstevel@tonic-gate return (1);
16790Sstevel@tonic-gate }
16800Sstevel@tonic-gate
16810Sstevel@tonic-gate kmutex_t atomic_nc_mutex;
16820Sstevel@tonic-gate
16830Sstevel@tonic-gate /*
16840Sstevel@tonic-gate * The following couple of routines are for userland drivers which
16850Sstevel@tonic-gate * do atomics to noncached addresses. This sort of worked on previous
16860Sstevel@tonic-gate * platforms -- the operation really wasn't atomic, but it didn't generate
16870Sstevel@tonic-gate * a trap as sun4u systems do.
16880Sstevel@tonic-gate */
16890Sstevel@tonic-gate static int
swap_nc(struct regs * rp,int instr)16900Sstevel@tonic-gate swap_nc(struct regs *rp, int instr)
16910Sstevel@tonic-gate {
16920Sstevel@tonic-gate uint64_t rdata, mdata;
16930Sstevel@tonic-gate caddr_t addr, badaddr;
16940Sstevel@tonic-gate uint_t tmp, rd;
16950Sstevel@tonic-gate
16960Sstevel@tonic-gate (void) flush_user_windows_to_stack(NULL);
16970Sstevel@tonic-gate rd = (instr >> 25) & 0x1f;
16980Sstevel@tonic-gate if (calc_memaddr(rp, &addr) != SIMU_SUCCESS)
16990Sstevel@tonic-gate return (0);
17000Sstevel@tonic-gate if (getreg(rp, rd, &rdata, &badaddr))
17010Sstevel@tonic-gate return (0);
17020Sstevel@tonic-gate mutex_enter(&atomic_nc_mutex);
17030Sstevel@tonic-gate if (fuword32(addr, &tmp) == -1) {
17040Sstevel@tonic-gate mutex_exit(&atomic_nc_mutex);
17050Sstevel@tonic-gate return (0);
17060Sstevel@tonic-gate }
17070Sstevel@tonic-gate mdata = (u_longlong_t)tmp;
17080Sstevel@tonic-gate if (suword32(addr, (uint32_t)rdata) == -1) {
17090Sstevel@tonic-gate mutex_exit(&atomic_nc_mutex);
17100Sstevel@tonic-gate return (0);
17110Sstevel@tonic-gate }
17120Sstevel@tonic-gate (void) putreg(&mdata, rp, rd, &badaddr);
17130Sstevel@tonic-gate mutex_exit(&atomic_nc_mutex);
17140Sstevel@tonic-gate return (1);
17150Sstevel@tonic-gate }
17160Sstevel@tonic-gate
17170Sstevel@tonic-gate static int
ldstub_nc(struct regs * rp,int instr)17180Sstevel@tonic-gate ldstub_nc(struct regs *rp, int instr)
17190Sstevel@tonic-gate {
17200Sstevel@tonic-gate uint64_t mdata;
17210Sstevel@tonic-gate caddr_t addr, badaddr;
17220Sstevel@tonic-gate uint_t rd;
17230Sstevel@tonic-gate uint8_t tmp;
17240Sstevel@tonic-gate
17250Sstevel@tonic-gate (void) flush_user_windows_to_stack(NULL);
17260Sstevel@tonic-gate rd = (instr >> 25) & 0x1f;
17270Sstevel@tonic-gate if (calc_memaddr(rp, &addr) != SIMU_SUCCESS)
17280Sstevel@tonic-gate return (0);
17290Sstevel@tonic-gate mutex_enter(&atomic_nc_mutex);
17300Sstevel@tonic-gate if (fuword8(addr, &tmp) == -1) {
17310Sstevel@tonic-gate mutex_exit(&atomic_nc_mutex);
17320Sstevel@tonic-gate return (0);
17330Sstevel@tonic-gate }
17340Sstevel@tonic-gate mdata = (u_longlong_t)tmp;
17350Sstevel@tonic-gate if (suword8(addr, (uint8_t)0xff) == -1) {
17360Sstevel@tonic-gate mutex_exit(&atomic_nc_mutex);
17370Sstevel@tonic-gate return (0);
17380Sstevel@tonic-gate }
17390Sstevel@tonic-gate (void) putreg(&mdata, rp, rd, &badaddr);
17400Sstevel@tonic-gate mutex_exit(&atomic_nc_mutex);
17410Sstevel@tonic-gate return (1);
17420Sstevel@tonic-gate }
17430Sstevel@tonic-gate
17440Sstevel@tonic-gate /*
17450Sstevel@tonic-gate * This function helps instr_size() determine the operand size.
17460Sstevel@tonic-gate * It is called for the extended ldda/stda asi's.
17470Sstevel@tonic-gate */
17480Sstevel@tonic-gate int
extended_asi_size(int asi)17490Sstevel@tonic-gate extended_asi_size(int asi)
17500Sstevel@tonic-gate {
17510Sstevel@tonic-gate switch (asi) {
17520Sstevel@tonic-gate case ASI_PST8_P:
17530Sstevel@tonic-gate case ASI_PST8_S:
17540Sstevel@tonic-gate case ASI_PST16_P:
17550Sstevel@tonic-gate case ASI_PST16_S:
17560Sstevel@tonic-gate case ASI_PST32_P:
17570Sstevel@tonic-gate case ASI_PST32_S:
17580Sstevel@tonic-gate case ASI_PST8_PL:
17590Sstevel@tonic-gate case ASI_PST8_SL:
17600Sstevel@tonic-gate case ASI_PST16_PL:
17610Sstevel@tonic-gate case ASI_PST16_SL:
17620Sstevel@tonic-gate case ASI_PST32_PL:
17630Sstevel@tonic-gate case ASI_PST32_SL:
17640Sstevel@tonic-gate return (8);
17650Sstevel@tonic-gate case ASI_FL8_P:
17660Sstevel@tonic-gate case ASI_FL8_S:
17670Sstevel@tonic-gate case ASI_FL8_PL:
17680Sstevel@tonic-gate case ASI_FL8_SL:
17690Sstevel@tonic-gate return (1);
17700Sstevel@tonic-gate case ASI_FL16_P:
17710Sstevel@tonic-gate case ASI_FL16_S:
17720Sstevel@tonic-gate case ASI_FL16_PL:
17730Sstevel@tonic-gate case ASI_FL16_SL:
17740Sstevel@tonic-gate return (2);
17750Sstevel@tonic-gate case ASI_BLK_P:
17760Sstevel@tonic-gate case ASI_BLK_S:
17770Sstevel@tonic-gate case ASI_BLK_PL:
17780Sstevel@tonic-gate case ASI_BLK_SL:
17790Sstevel@tonic-gate case ASI_BLK_COMMIT_P:
17800Sstevel@tonic-gate case ASI_BLK_COMMIT_S:
17810Sstevel@tonic-gate return (64);
17820Sstevel@tonic-gate }
17830Sstevel@tonic-gate
17840Sstevel@tonic-gate return (0);
17850Sstevel@tonic-gate }
17860Sstevel@tonic-gate
17870Sstevel@tonic-gate /*
17880Sstevel@tonic-gate * Patch non-zero to disable preemption of threads in the kernel.
17890Sstevel@tonic-gate */
17900Sstevel@tonic-gate int IGNORE_KERNEL_PREEMPTION = 0; /* XXX - delete this someday */
17910Sstevel@tonic-gate
17920Sstevel@tonic-gate struct kpreempt_cnts { /* kernel preemption statistics */
17930Sstevel@tonic-gate int kpc_idle; /* executing idle thread */
17940Sstevel@tonic-gate int kpc_intr; /* executing interrupt thread */
17950Sstevel@tonic-gate int kpc_clock; /* executing clock thread */
17960Sstevel@tonic-gate int kpc_blocked; /* thread has blocked preemption (t_preempt) */
17970Sstevel@tonic-gate int kpc_notonproc; /* thread is surrendering processor */
17980Sstevel@tonic-gate int kpc_inswtch; /* thread has ratified scheduling decision */
17990Sstevel@tonic-gate int kpc_prilevel; /* processor interrupt level is too high */
18000Sstevel@tonic-gate int kpc_apreempt; /* asynchronous preemption */
18010Sstevel@tonic-gate int kpc_spreempt; /* synchronous preemption */
18020Sstevel@tonic-gate } kpreempt_cnts;
18030Sstevel@tonic-gate
18040Sstevel@tonic-gate /*
18050Sstevel@tonic-gate * kernel preemption: forced rescheduling
18060Sstevel@tonic-gate * preempt the running kernel thread.
18070Sstevel@tonic-gate */
18080Sstevel@tonic-gate void
kpreempt(int asyncspl)18090Sstevel@tonic-gate kpreempt(int asyncspl)
18100Sstevel@tonic-gate {
18110Sstevel@tonic-gate if (IGNORE_KERNEL_PREEMPTION) {
18120Sstevel@tonic-gate aston(CPU->cpu_dispthread);
18130Sstevel@tonic-gate return;
18140Sstevel@tonic-gate }
18150Sstevel@tonic-gate /*
18160Sstevel@tonic-gate * Check that conditions are right for kernel preemption
18170Sstevel@tonic-gate */
18180Sstevel@tonic-gate do {
18190Sstevel@tonic-gate if (curthread->t_preempt) {
18200Sstevel@tonic-gate /*
18210Sstevel@tonic-gate * either a privileged thread (idle, panic, interrupt)
18228173SPramod.Batni@Sun.COM * or will check when t_preempt is lowered
18238173SPramod.Batni@Sun.COM * We need to specifically handle the case where
18248173SPramod.Batni@Sun.COM * the thread is in the middle of swtch (resume has
18258173SPramod.Batni@Sun.COM * been called) and has its t_preempt set
18268173SPramod.Batni@Sun.COM * [idle thread and a thread which is in kpreempt
18278173SPramod.Batni@Sun.COM * already] and then a high priority thread is
18288173SPramod.Batni@Sun.COM * available in the local dispatch queue.
18298173SPramod.Batni@Sun.COM * In this case the resumed thread needs to take a
18308173SPramod.Batni@Sun.COM * trap so that it can call kpreempt. We achieve
18318173SPramod.Batni@Sun.COM * this by using siron().
18328173SPramod.Batni@Sun.COM * How do we detect this condition:
18338173SPramod.Batni@Sun.COM * idle thread is running and is in the midst of
18348173SPramod.Batni@Sun.COM * resume: curthread->t_pri == -1 && CPU->dispthread
18358173SPramod.Batni@Sun.COM * != CPU->thread
18368173SPramod.Batni@Sun.COM * Need to ensure that this happens only at high pil
18378173SPramod.Batni@Sun.COM * resume is called at high pil
18388173SPramod.Batni@Sun.COM * Only in resume_from_idle is the pil changed.
18390Sstevel@tonic-gate */
18408173SPramod.Batni@Sun.COM if (curthread->t_pri < 0) {
18410Sstevel@tonic-gate kpreempt_cnts.kpc_idle++;
18428173SPramod.Batni@Sun.COM if (CPU->cpu_dispthread != CPU->cpu_thread)
18438173SPramod.Batni@Sun.COM siron();
18448173SPramod.Batni@Sun.COM } else if (curthread->t_flag & T_INTR_THREAD) {
18450Sstevel@tonic-gate kpreempt_cnts.kpc_intr++;
18460Sstevel@tonic-gate if (curthread->t_pil == CLOCK_LEVEL)
18470Sstevel@tonic-gate kpreempt_cnts.kpc_clock++;
18488173SPramod.Batni@Sun.COM } else {
18490Sstevel@tonic-gate kpreempt_cnts.kpc_blocked++;
18508173SPramod.Batni@Sun.COM if (CPU->cpu_dispthread != CPU->cpu_thread)
18518173SPramod.Batni@Sun.COM siron();
18528173SPramod.Batni@Sun.COM }
18530Sstevel@tonic-gate aston(CPU->cpu_dispthread);
18540Sstevel@tonic-gate return;
18550Sstevel@tonic-gate }
18560Sstevel@tonic-gate if (curthread->t_state != TS_ONPROC ||
18570Sstevel@tonic-gate curthread->t_disp_queue != CPU->cpu_disp) {
18580Sstevel@tonic-gate /* this thread will be calling swtch() shortly */
18590Sstevel@tonic-gate kpreempt_cnts.kpc_notonproc++;
18600Sstevel@tonic-gate if (CPU->cpu_thread != CPU->cpu_dispthread) {
18610Sstevel@tonic-gate /* already in swtch(), force another */
18620Sstevel@tonic-gate kpreempt_cnts.kpc_inswtch++;
18630Sstevel@tonic-gate siron();
18640Sstevel@tonic-gate }
18650Sstevel@tonic-gate return;
18660Sstevel@tonic-gate }
18670Sstevel@tonic-gate
18680Sstevel@tonic-gate if (((asyncspl != KPREEMPT_SYNC) ? spltoipl(asyncspl) :
18690Sstevel@tonic-gate getpil()) >= DISP_LEVEL) {
18700Sstevel@tonic-gate /*
18710Sstevel@tonic-gate * We can't preempt this thread if it is at
18720Sstevel@tonic-gate * a PIL >= DISP_LEVEL since it may be holding
18730Sstevel@tonic-gate * a spin lock (like sched_lock).
18740Sstevel@tonic-gate */
18750Sstevel@tonic-gate siron(); /* check back later */
18760Sstevel@tonic-gate kpreempt_cnts.kpc_prilevel++;
18770Sstevel@tonic-gate return;
18780Sstevel@tonic-gate }
18790Sstevel@tonic-gate
18800Sstevel@tonic-gate /*
18810Sstevel@tonic-gate * block preemption so we don't have multiple preemptions
18820Sstevel@tonic-gate * pending on the interrupt stack
18830Sstevel@tonic-gate */
18840Sstevel@tonic-gate curthread->t_preempt++;
18850Sstevel@tonic-gate if (asyncspl != KPREEMPT_SYNC) {
18860Sstevel@tonic-gate splx(asyncspl);
18870Sstevel@tonic-gate kpreempt_cnts.kpc_apreempt++;
18880Sstevel@tonic-gate } else
18890Sstevel@tonic-gate kpreempt_cnts.kpc_spreempt++;
18900Sstevel@tonic-gate
18910Sstevel@tonic-gate preempt();
18920Sstevel@tonic-gate curthread->t_preempt--;
18930Sstevel@tonic-gate } while (CPU->cpu_kprunrun);
18940Sstevel@tonic-gate }
18950Sstevel@tonic-gate
18960Sstevel@tonic-gate static enum seg_rw
get_accesstype(struct regs * rp)18970Sstevel@tonic-gate get_accesstype(struct regs *rp)
18980Sstevel@tonic-gate {
18990Sstevel@tonic-gate uint32_t instr;
19000Sstevel@tonic-gate
19010Sstevel@tonic-gate if (USERMODE(rp->r_tstate))
19020Sstevel@tonic-gate instr = fetch_user_instr((caddr_t)rp->r_pc);
19030Sstevel@tonic-gate else
19040Sstevel@tonic-gate instr = *(uint32_t *)rp->r_pc;
19050Sstevel@tonic-gate
19060Sstevel@tonic-gate if (IS_FLUSH(instr))
19070Sstevel@tonic-gate return (S_OTHER);
19080Sstevel@tonic-gate
19090Sstevel@tonic-gate if (IS_STORE(instr))
19100Sstevel@tonic-gate return (S_WRITE);
19110Sstevel@tonic-gate else
19120Sstevel@tonic-gate return (S_READ);
19130Sstevel@tonic-gate }
19149613SAbhinandan.Ekande@Sun.COM
19159613SAbhinandan.Ekande@Sun.COM /*
19169613SAbhinandan.Ekande@Sun.COM * Handle an asynchronous hardware error.
19179613SAbhinandan.Ekande@Sun.COM * The policy is currently to send a hardware error contract event to
19189613SAbhinandan.Ekande@Sun.COM * the process's process contract and to kill the process. Eventually
19199613SAbhinandan.Ekande@Sun.COM * we may want to instead send a special signal whose default
19209613SAbhinandan.Ekande@Sun.COM * disposition is to generate the contract event.
19219613SAbhinandan.Ekande@Sun.COM */
19229613SAbhinandan.Ekande@Sun.COM void
trap_async_hwerr(void)19239613SAbhinandan.Ekande@Sun.COM trap_async_hwerr(void)
19249613SAbhinandan.Ekande@Sun.COM {
19259613SAbhinandan.Ekande@Sun.COM k_siginfo_t si;
19269613SAbhinandan.Ekande@Sun.COM proc_t *p = ttoproc(curthread);
19279613SAbhinandan.Ekande@Sun.COM extern void print_msg_hwerr(ctid_t ct_id, proc_t *p);
19289613SAbhinandan.Ekande@Sun.COM
19299613SAbhinandan.Ekande@Sun.COM errorq_drain(ue_queue); /* flush pending async error messages */
19309613SAbhinandan.Ekande@Sun.COM
19319613SAbhinandan.Ekande@Sun.COM print_msg_hwerr(p->p_ct_process->conp_contract.ct_id, p);
19329613SAbhinandan.Ekande@Sun.COM
19339613SAbhinandan.Ekande@Sun.COM contract_process_hwerr(p->p_ct_process, p);
19349613SAbhinandan.Ekande@Sun.COM
19359613SAbhinandan.Ekande@Sun.COM bzero(&si, sizeof (k_siginfo_t));
19369613SAbhinandan.Ekande@Sun.COM si.si_signo = SIGKILL;
19379613SAbhinandan.Ekande@Sun.COM si.si_code = SI_NOINFO;
19389613SAbhinandan.Ekande@Sun.COM trapsig(&si, 1);
19399613SAbhinandan.Ekande@Sun.COM }
19409613SAbhinandan.Ekande@Sun.COM
19419613SAbhinandan.Ekande@Sun.COM /*
19429613SAbhinandan.Ekande@Sun.COM * Handle bus error and bus timeout for a user process by sending SIGBUS
19439613SAbhinandan.Ekande@Sun.COM * The type is either ASYNC_BERR or ASYNC_BTO.
19449613SAbhinandan.Ekande@Sun.COM */
19459613SAbhinandan.Ekande@Sun.COM void
trap_async_berr_bto(int type,struct regs * rp)19469613SAbhinandan.Ekande@Sun.COM trap_async_berr_bto(int type, struct regs *rp)
19479613SAbhinandan.Ekande@Sun.COM {
19489613SAbhinandan.Ekande@Sun.COM k_siginfo_t si;
19499613SAbhinandan.Ekande@Sun.COM
19509613SAbhinandan.Ekande@Sun.COM errorq_drain(ue_queue); /* flush pending async error messages */
19519613SAbhinandan.Ekande@Sun.COM bzero(&si, sizeof (k_siginfo_t));
19529613SAbhinandan.Ekande@Sun.COM
19539613SAbhinandan.Ekande@Sun.COM si.si_signo = SIGBUS;
19549613SAbhinandan.Ekande@Sun.COM si.si_code = (type == ASYNC_BERR ? BUS_OBJERR : BUS_ADRERR);
19559613SAbhinandan.Ekande@Sun.COM si.si_addr = (caddr_t)rp->r_pc; /* AFAR unavailable - future RFE */
19569613SAbhinandan.Ekande@Sun.COM si.si_errno = ENXIO;
19579613SAbhinandan.Ekande@Sun.COM
19589613SAbhinandan.Ekande@Sun.COM trapsig(&si, 1);
19599613SAbhinandan.Ekande@Sun.COM }
1960