17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5efd37614Sdv142724 * Common Development and Distribution License (the "License").
6efd37614Sdv142724 * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
219acbbeafSnn35248
227c478bd9Sstevel@tonic-gate /*
23d6c90996SAbhinandan Ekande * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
2769c92249SBryan Cantrill /*
2869c92249SBryan Cantrill * Copyright (c) 2012 Joyent, Inc. All rights reserved.
2969c92249SBryan Cantrill */
307c478bd9Sstevel@tonic-gate
317c478bd9Sstevel@tonic-gate #include <sys/mmu.h>
327c478bd9Sstevel@tonic-gate #include <sys/systm.h>
337c478bd9Sstevel@tonic-gate #include <sys/trap.h>
347c478bd9Sstevel@tonic-gate #include <sys/machtrap.h>
357c478bd9Sstevel@tonic-gate #include <sys/vtrace.h>
367c478bd9Sstevel@tonic-gate #include <sys/prsystm.h>
377c478bd9Sstevel@tonic-gate #include <sys/archsystm.h>
387c478bd9Sstevel@tonic-gate #include <sys/machsystm.h>
397c478bd9Sstevel@tonic-gate #include <sys/fpu/fpusystm.h>
407c478bd9Sstevel@tonic-gate #include <sys/tnf.h>
417c478bd9Sstevel@tonic-gate #include <sys/tnf_probe.h>
427c478bd9Sstevel@tonic-gate #include <sys/simulate.h>
437c478bd9Sstevel@tonic-gate #include <sys/ftrace.h>
447c478bd9Sstevel@tonic-gate #include <sys/ontrap.h>
457c478bd9Sstevel@tonic-gate #include <sys/kcpc.h>
467c478bd9Sstevel@tonic-gate #include <sys/kobj.h>
477c478bd9Sstevel@tonic-gate #include <sys/procfs.h>
487c478bd9Sstevel@tonic-gate #include <sys/sun4asi.h>
497c478bd9Sstevel@tonic-gate #include <sys/sdt.h>
507c478bd9Sstevel@tonic-gate #include <sys/fpras.h>
51d6c90996SAbhinandan Ekande #include <sys/contract/process_impl.h>
527c478bd9Sstevel@tonic-gate
537c478bd9Sstevel@tonic-gate #ifdef TRAPTRACE
547c478bd9Sstevel@tonic-gate #include <sys/traptrace.h>
557c478bd9Sstevel@tonic-gate #endif
567c478bd9Sstevel@tonic-gate
577c478bd9Sstevel@tonic-gate int tudebug = 0;
587c478bd9Sstevel@tonic-gate static int tudebugbpt = 0;
597c478bd9Sstevel@tonic-gate static int tudebugfpe = 0;
607c478bd9Sstevel@tonic-gate
617c478bd9Sstevel@tonic-gate static int alignfaults = 0;
627c478bd9Sstevel@tonic-gate
637c478bd9Sstevel@tonic-gate #if defined(TRAPDEBUG) || defined(lint)
647c478bd9Sstevel@tonic-gate static int lodebug = 0;
657c478bd9Sstevel@tonic-gate #else
667c478bd9Sstevel@tonic-gate #define lodebug 0
677c478bd9Sstevel@tonic-gate #endif /* defined(TRAPDEBUG) || defined(lint) */
687c478bd9Sstevel@tonic-gate
697c478bd9Sstevel@tonic-gate
707c478bd9Sstevel@tonic-gate int vis1_partial_support(struct regs *rp, k_siginfo_t *siginfo, uint_t *fault);
717c478bd9Sstevel@tonic-gate #pragma weak vis1_partial_support
727c478bd9Sstevel@tonic-gate
737c478bd9Sstevel@tonic-gate void showregs(unsigned, struct regs *, caddr_t, uint_t);
747c478bd9Sstevel@tonic-gate #pragma weak showregs
757c478bd9Sstevel@tonic-gate
767c478bd9Sstevel@tonic-gate void trap_async_hwerr(void);
777c478bd9Sstevel@tonic-gate #pragma weak trap_async_hwerr
787c478bd9Sstevel@tonic-gate
797c478bd9Sstevel@tonic-gate void trap_async_berr_bto(int, struct regs *);
807c478bd9Sstevel@tonic-gate #pragma weak trap_async_berr_bto
817c478bd9Sstevel@tonic-gate
827c478bd9Sstevel@tonic-gate static enum seg_rw get_accesstype(struct regs *);
837c478bd9Sstevel@tonic-gate static int nfload(struct regs *, int *);
847c478bd9Sstevel@tonic-gate static int swap_nc(struct regs *, int);
857c478bd9Sstevel@tonic-gate static int ldstub_nc(struct regs *, int);
867c478bd9Sstevel@tonic-gate void trap_cleanup(struct regs *, uint_t, k_siginfo_t *, int);
877c478bd9Sstevel@tonic-gate void trap_rtt(void);
887c478bd9Sstevel@tonic-gate
897c478bd9Sstevel@tonic-gate static int
die(unsigned type,struct regs * rp,caddr_t addr,uint_t mmu_fsr)907c478bd9Sstevel@tonic-gate die(unsigned type, struct regs *rp, caddr_t addr, uint_t mmu_fsr)
917c478bd9Sstevel@tonic-gate {
92843e1988Sjohnlev struct panic_trap_info ti;
937c478bd9Sstevel@tonic-gate
947c478bd9Sstevel@tonic-gate #ifdef TRAPTRACE
957c478bd9Sstevel@tonic-gate TRAPTRACE_FREEZE;
967c478bd9Sstevel@tonic-gate #endif
977c478bd9Sstevel@tonic-gate
987c478bd9Sstevel@tonic-gate ti.trap_regs = rp;
997c478bd9Sstevel@tonic-gate ti.trap_type = type;
1007c478bd9Sstevel@tonic-gate ti.trap_addr = addr;
1017c478bd9Sstevel@tonic-gate ti.trap_mmu_fsr = mmu_fsr;
1027c478bd9Sstevel@tonic-gate
1037c478bd9Sstevel@tonic-gate curthread->t_panic_trap = &ti;
1047c478bd9Sstevel@tonic-gate
1057c478bd9Sstevel@tonic-gate if (type == T_DATA_MMU_MISS && addr < (caddr_t)KERNELBASE) {
1067c478bd9Sstevel@tonic-gate panic("BAD TRAP: type=%x rp=%p addr=%p mmu_fsr=%x "
1077c478bd9Sstevel@tonic-gate "occurred in module \"%s\" due to %s",
1087c478bd9Sstevel@tonic-gate type, (void *)rp, (void *)addr, mmu_fsr,
1097c478bd9Sstevel@tonic-gate mod_containing_pc((caddr_t)rp->r_pc),
1107c478bd9Sstevel@tonic-gate addr < (caddr_t)PAGESIZE ?
1117c478bd9Sstevel@tonic-gate "a NULL pointer dereference" :
1127c478bd9Sstevel@tonic-gate "an illegal access to a user address");
1137c478bd9Sstevel@tonic-gate } else {
1147c478bd9Sstevel@tonic-gate panic("BAD TRAP: type=%x rp=%p addr=%p mmu_fsr=%x",
1157c478bd9Sstevel@tonic-gate type, (void *)rp, (void *)addr, mmu_fsr);
1167c478bd9Sstevel@tonic-gate }
1177c478bd9Sstevel@tonic-gate
1187c478bd9Sstevel@tonic-gate return (0); /* avoid optimization of restore in call's delay slot */
1197c478bd9Sstevel@tonic-gate }
1207c478bd9Sstevel@tonic-gate
1217c478bd9Sstevel@tonic-gate #if defined(SF_ERRATA_23) || defined(SF_ERRATA_30) /* call ... illegal-insn */
1227c478bd9Sstevel@tonic-gate int ill_calls;
1237c478bd9Sstevel@tonic-gate #endif
1247c478bd9Sstevel@tonic-gate
1257c478bd9Sstevel@tonic-gate /*
1267c478bd9Sstevel@tonic-gate * Currently, the only PREFETCH/PREFETCHA instructions which cause traps
1277c478bd9Sstevel@tonic-gate * are the "strong" prefetches (fcn=20-23). But we check for all flavors of
1287c478bd9Sstevel@tonic-gate * PREFETCH, in case some future variant also causes a DATA_MMU_MISS.
1297c478bd9Sstevel@tonic-gate */
1307c478bd9Sstevel@tonic-gate #define IS_PREFETCH(i) (((i) & 0xc1780000) == 0xc1680000)
1317c478bd9Sstevel@tonic-gate
1327c478bd9Sstevel@tonic-gate #define IS_FLUSH(i) (((i) & 0xc1f80000) == 0x81d80000)
1337c478bd9Sstevel@tonic-gate #define IS_SWAP(i) (((i) & 0xc1f80000) == 0xc0780000)
1347c478bd9Sstevel@tonic-gate #define IS_LDSTUB(i) (((i) & 0xc1f80000) == 0xc0680000)
1357c478bd9Sstevel@tonic-gate #define IS_FLOAT(i) (((i) & 0x1000000) != 0)
1367c478bd9Sstevel@tonic-gate #define IS_STORE(i) (((i) >> 21) & 1)
1377c478bd9Sstevel@tonic-gate
1387c478bd9Sstevel@tonic-gate /*
1397c478bd9Sstevel@tonic-gate * Called from the trap handler when a processor trap occurs.
1407c478bd9Sstevel@tonic-gate */
1417c478bd9Sstevel@tonic-gate /*VARARGS2*/
1427c478bd9Sstevel@tonic-gate void
trap(struct regs * rp,caddr_t addr,uint32_t type,uint32_t mmu_fsr)1437c478bd9Sstevel@tonic-gate trap(struct regs *rp, caddr_t addr, uint32_t type, uint32_t mmu_fsr)
1447c478bd9Sstevel@tonic-gate {
1457c478bd9Sstevel@tonic-gate proc_t *p = ttoproc(curthread);
1467c478bd9Sstevel@tonic-gate klwp_id_t lwp = ttolwp(curthread);
1477c478bd9Sstevel@tonic-gate struct machpcb *mpcb = NULL;
1487c478bd9Sstevel@tonic-gate k_siginfo_t siginfo;
1497c478bd9Sstevel@tonic-gate uint_t op3, fault = 0;
1507c478bd9Sstevel@tonic-gate int stepped = 0;
1517c478bd9Sstevel@tonic-gate greg_t oldpc;
1527c478bd9Sstevel@tonic-gate int mstate;
1537c478bd9Sstevel@tonic-gate char *badaddr;
1547c478bd9Sstevel@tonic-gate faultcode_t res;
1557c478bd9Sstevel@tonic-gate enum fault_type fault_type;
1567c478bd9Sstevel@tonic-gate enum seg_rw rw;
1577c478bd9Sstevel@tonic-gate uintptr_t lofault;
15869c92249SBryan Cantrill label_t *onfault;
1597c478bd9Sstevel@tonic-gate int instr;
1607c478bd9Sstevel@tonic-gate int iskernel;
1617c478bd9Sstevel@tonic-gate int watchcode;
1627c478bd9Sstevel@tonic-gate int watchpage;
1637c478bd9Sstevel@tonic-gate extern faultcode_t pagefault(caddr_t, enum fault_type,
1647c478bd9Sstevel@tonic-gate enum seg_rw, int);
165023e71deSHaik Aftandilian #ifdef sun4v
166023e71deSHaik Aftandilian extern boolean_t tick_stick_emulation_active;
167023e71deSHaik Aftandilian #endif /* sun4v */
1687c478bd9Sstevel@tonic-gate
1697c478bd9Sstevel@tonic-gate CPU_STATS_ADDQ(CPU, sys, trap, 1);
1707c478bd9Sstevel@tonic-gate
1717c478bd9Sstevel@tonic-gate #ifdef SF_ERRATA_23 /* call causes illegal-insn */
1727c478bd9Sstevel@tonic-gate ASSERT((curthread->t_schedflag & TS_DONT_SWAP) ||
1737c478bd9Sstevel@tonic-gate (type == T_UNIMP_INSTR));
1747c478bd9Sstevel@tonic-gate #else
1757c478bd9Sstevel@tonic-gate ASSERT(curthread->t_schedflag & TS_DONT_SWAP);
1767c478bd9Sstevel@tonic-gate #endif /* SF_ERRATA_23 */
1777c478bd9Sstevel@tonic-gate
1787c478bd9Sstevel@tonic-gate if (USERMODE(rp->r_tstate) || (type & T_USER)) {
1797c478bd9Sstevel@tonic-gate /*
1807c478bd9Sstevel@tonic-gate * Set lwp_state before trying to acquire any
1817c478bd9Sstevel@tonic-gate * adaptive lock
1827c478bd9Sstevel@tonic-gate */
1837c478bd9Sstevel@tonic-gate ASSERT(lwp != NULL);
1847c478bd9Sstevel@tonic-gate lwp->lwp_state = LWP_SYS;
1857c478bd9Sstevel@tonic-gate /*
1867c478bd9Sstevel@tonic-gate * Set up the current cred to use during this trap. u_cred
1877c478bd9Sstevel@tonic-gate * no longer exists. t_cred is used instead.
1887c478bd9Sstevel@tonic-gate * The current process credential applies to the thread for
1897c478bd9Sstevel@tonic-gate * the entire trap. If trapping from the kernel, this
1907c478bd9Sstevel@tonic-gate * should already be set up.
1917c478bd9Sstevel@tonic-gate */
1927c478bd9Sstevel@tonic-gate if (curthread->t_cred != p->p_cred) {
1937c478bd9Sstevel@tonic-gate cred_t *oldcred = curthread->t_cred;
1947c478bd9Sstevel@tonic-gate /*
1957c478bd9Sstevel@tonic-gate * DTrace accesses t_cred in probe context. t_cred
1967c478bd9Sstevel@tonic-gate * must always be either NULL, or point to a valid,
1977c478bd9Sstevel@tonic-gate * allocated cred structure.
1987c478bd9Sstevel@tonic-gate */
1997c478bd9Sstevel@tonic-gate curthread->t_cred = crgetcred();
2007c478bd9Sstevel@tonic-gate crfree(oldcred);
2017c478bd9Sstevel@tonic-gate }
2027c478bd9Sstevel@tonic-gate type |= T_USER;
2037c478bd9Sstevel@tonic-gate ASSERT((type == (T_SYS_RTT_PAGE | T_USER)) ||
2047c478bd9Sstevel@tonic-gate (type == (T_SYS_RTT_ALIGN | T_USER)) ||
2057c478bd9Sstevel@tonic-gate lwp->lwp_regs == rp);
2067c478bd9Sstevel@tonic-gate mpcb = lwptompcb(lwp);
2077c478bd9Sstevel@tonic-gate switch (type) {
2087c478bd9Sstevel@tonic-gate case T_WIN_OVERFLOW + T_USER:
2097c478bd9Sstevel@tonic-gate case T_WIN_UNDERFLOW + T_USER:
2107c478bd9Sstevel@tonic-gate case T_SYS_RTT_PAGE + T_USER:
2117c478bd9Sstevel@tonic-gate case T_DATA_MMU_MISS + T_USER:
2127c478bd9Sstevel@tonic-gate mstate = LMS_DFAULT;
2137c478bd9Sstevel@tonic-gate break;
2147c478bd9Sstevel@tonic-gate case T_INSTR_MMU_MISS + T_USER:
2157c478bd9Sstevel@tonic-gate mstate = LMS_TFAULT;
2167c478bd9Sstevel@tonic-gate break;
2177c478bd9Sstevel@tonic-gate default:
2187c478bd9Sstevel@tonic-gate mstate = LMS_TRAP;
2197c478bd9Sstevel@tonic-gate break;
2207c478bd9Sstevel@tonic-gate }
2217c478bd9Sstevel@tonic-gate /* Kernel probe */
2227c478bd9Sstevel@tonic-gate TNF_PROBE_1(thread_state, "thread", /* CSTYLED */,
2237c478bd9Sstevel@tonic-gate tnf_microstate, state, (char)mstate);
2247c478bd9Sstevel@tonic-gate mstate = new_mstate(curthread, mstate);
2257c478bd9Sstevel@tonic-gate siginfo.si_signo = 0;
2267c478bd9Sstevel@tonic-gate stepped =
2277c478bd9Sstevel@tonic-gate lwp->lwp_pcb.pcb_step != STEP_NONE &&
2287c478bd9Sstevel@tonic-gate ((oldpc = rp->r_pc), prundostep()) &&
2297c478bd9Sstevel@tonic-gate mmu_btop((uintptr_t)addr) == mmu_btop((uintptr_t)oldpc);
2307c478bd9Sstevel@tonic-gate /* this assignment must not precede call to prundostep() */
2317c478bd9Sstevel@tonic-gate oldpc = rp->r_pc;
2327c478bd9Sstevel@tonic-gate }
2337c478bd9Sstevel@tonic-gate
2347c478bd9Sstevel@tonic-gate TRACE_1(TR_FAC_TRAP, TR_C_TRAP_HANDLER_ENTER,
2357c478bd9Sstevel@tonic-gate "C_trap_handler_enter:type %x", type);
2367c478bd9Sstevel@tonic-gate
2377c478bd9Sstevel@tonic-gate #ifdef F_DEFERRED
2387c478bd9Sstevel@tonic-gate /*
2397c478bd9Sstevel@tonic-gate * Take any pending floating point exceptions now.
2407c478bd9Sstevel@tonic-gate * If the floating point unit has an exception to handle,
2417c478bd9Sstevel@tonic-gate * just return to user-level to let the signal handler run.
2427c478bd9Sstevel@tonic-gate * The instruction that got us to trap() will be reexecuted on
2437c478bd9Sstevel@tonic-gate * return from the signal handler and we will trap to here again.
2447c478bd9Sstevel@tonic-gate * This is necessary to disambiguate simultaneous traps which
2457c478bd9Sstevel@tonic-gate * happen when a floating-point exception is pending and a
2467c478bd9Sstevel@tonic-gate * machine fault is incurred.
2477c478bd9Sstevel@tonic-gate */
2487c478bd9Sstevel@tonic-gate if (type & USER) {
2497c478bd9Sstevel@tonic-gate /*
2507c478bd9Sstevel@tonic-gate * FP_TRAPPED is set only by sendsig() when it copies
2517c478bd9Sstevel@tonic-gate * out the floating-point queue for the signal handler.
2527c478bd9Sstevel@tonic-gate * It is set there so we can test it here and in syscall().
2537c478bd9Sstevel@tonic-gate */
2547c478bd9Sstevel@tonic-gate mpcb->mpcb_flags &= ~FP_TRAPPED;
2557c478bd9Sstevel@tonic-gate syncfpu();
2567c478bd9Sstevel@tonic-gate if (mpcb->mpcb_flags & FP_TRAPPED) {
2577c478bd9Sstevel@tonic-gate /*
2587c478bd9Sstevel@tonic-gate * trap() has have been called recursively and may
2597c478bd9Sstevel@tonic-gate * have stopped the process, so do single step
2607c478bd9Sstevel@tonic-gate * support for /proc.
2617c478bd9Sstevel@tonic-gate */
2627c478bd9Sstevel@tonic-gate mpcb->mpcb_flags &= ~FP_TRAPPED;
2637c478bd9Sstevel@tonic-gate goto out;
2647c478bd9Sstevel@tonic-gate }
2657c478bd9Sstevel@tonic-gate }
2667c478bd9Sstevel@tonic-gate #endif
2677c478bd9Sstevel@tonic-gate switch (type) {
2687c478bd9Sstevel@tonic-gate case T_DATA_MMU_MISS:
2697c478bd9Sstevel@tonic-gate case T_INSTR_MMU_MISS + T_USER:
2707c478bd9Sstevel@tonic-gate case T_DATA_MMU_MISS + T_USER:
2717c478bd9Sstevel@tonic-gate case T_DATA_PROT + T_USER:
2727c478bd9Sstevel@tonic-gate case T_AST + T_USER:
2737c478bd9Sstevel@tonic-gate case T_SYS_RTT_PAGE + T_USER:
2747c478bd9Sstevel@tonic-gate case T_FLUSH_PCB + T_USER:
2757c478bd9Sstevel@tonic-gate case T_FLUSHW + T_USER:
2767c478bd9Sstevel@tonic-gate break;
2777c478bd9Sstevel@tonic-gate
2787c478bd9Sstevel@tonic-gate default:
2797c478bd9Sstevel@tonic-gate FTRACE_3("trap(): type=0x%lx, regs=0x%lx, addr=0x%lx",
2807c478bd9Sstevel@tonic-gate (ulong_t)type, (ulong_t)rp, (ulong_t)addr);
2817c478bd9Sstevel@tonic-gate break;
2827c478bd9Sstevel@tonic-gate }
2837c478bd9Sstevel@tonic-gate
2847c478bd9Sstevel@tonic-gate switch (type) {
2857c478bd9Sstevel@tonic-gate
2867c478bd9Sstevel@tonic-gate default:
2877c478bd9Sstevel@tonic-gate /*
2887c478bd9Sstevel@tonic-gate * Check for user software trap.
2897c478bd9Sstevel@tonic-gate */
2907c478bd9Sstevel@tonic-gate if (type & T_USER) {
2917c478bd9Sstevel@tonic-gate if (tudebug)
2927c478bd9Sstevel@tonic-gate showregs(type, rp, (caddr_t)0, 0);
2937c478bd9Sstevel@tonic-gate if ((type & ~T_USER) >= T_SOFTWARE_TRAP) {
2947c478bd9Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
2957c478bd9Sstevel@tonic-gate siginfo.si_signo = SIGILL;
2967c478bd9Sstevel@tonic-gate siginfo.si_code = ILL_ILLTRP;
2977c478bd9Sstevel@tonic-gate siginfo.si_addr = (caddr_t)rp->r_pc;
2987c478bd9Sstevel@tonic-gate siginfo.si_trapno = type &~ T_USER;
2997c478bd9Sstevel@tonic-gate fault = FLTILL;
3007c478bd9Sstevel@tonic-gate break;
3017c478bd9Sstevel@tonic-gate }
3027c478bd9Sstevel@tonic-gate }
3037c478bd9Sstevel@tonic-gate addr = (caddr_t)rp->r_pc;
3047c478bd9Sstevel@tonic-gate (void) die(type, rp, addr, 0);
3057c478bd9Sstevel@tonic-gate /*NOTREACHED*/
3067c478bd9Sstevel@tonic-gate
3077c478bd9Sstevel@tonic-gate case T_ALIGNMENT: /* supv alignment error */
3087c478bd9Sstevel@tonic-gate if (nfload(rp, NULL))
3097c478bd9Sstevel@tonic-gate goto cleanup;
3107c478bd9Sstevel@tonic-gate
3117c478bd9Sstevel@tonic-gate if (curthread->t_lofault) {
3127c478bd9Sstevel@tonic-gate if (lodebug) {
3137c478bd9Sstevel@tonic-gate showregs(type, rp, addr, 0);
3147c478bd9Sstevel@tonic-gate traceback((caddr_t)rp->r_sp);
3157c478bd9Sstevel@tonic-gate }
3167c478bd9Sstevel@tonic-gate rp->r_g1 = EFAULT;
3177c478bd9Sstevel@tonic-gate rp->r_pc = curthread->t_lofault;
3187c478bd9Sstevel@tonic-gate rp->r_npc = rp->r_pc + 4;
3197c478bd9Sstevel@tonic-gate goto cleanup;
3207c478bd9Sstevel@tonic-gate }
3217c478bd9Sstevel@tonic-gate (void) die(type, rp, addr, 0);
3227c478bd9Sstevel@tonic-gate /*NOTREACHED*/
3237c478bd9Sstevel@tonic-gate
3247c478bd9Sstevel@tonic-gate case T_INSTR_EXCEPTION: /* sys instruction access exception */
3257c478bd9Sstevel@tonic-gate addr = (caddr_t)rp->r_pc;
3267c478bd9Sstevel@tonic-gate (void) die(type, rp, addr, mmu_fsr);
3277c478bd9Sstevel@tonic-gate /*NOTREACHED*/
3287c478bd9Sstevel@tonic-gate
3297c478bd9Sstevel@tonic-gate case T_INSTR_MMU_MISS: /* sys instruction mmu miss */
3307c478bd9Sstevel@tonic-gate addr = (caddr_t)rp->r_pc;
3317c478bd9Sstevel@tonic-gate (void) die(type, rp, addr, 0);
3327c478bd9Sstevel@tonic-gate /*NOTREACHED*/
3337c478bd9Sstevel@tonic-gate
3347c478bd9Sstevel@tonic-gate case T_DATA_EXCEPTION: /* system data access exception */
3357c478bd9Sstevel@tonic-gate switch (X_FAULT_TYPE(mmu_fsr)) {
3367c478bd9Sstevel@tonic-gate case FT_RANGE:
3377c478bd9Sstevel@tonic-gate /*
3387c478bd9Sstevel@tonic-gate * This happens when we attempt to dereference an
3397c478bd9Sstevel@tonic-gate * address in the address hole. If t_ontrap is set,
3407c478bd9Sstevel@tonic-gate * then break and fall through to T_DATA_MMU_MISS /
3417c478bd9Sstevel@tonic-gate * T_DATA_PROT case below. If lofault is set, then
3427c478bd9Sstevel@tonic-gate * honour it (perhaps the user gave us a bogus
3437c478bd9Sstevel@tonic-gate * address in the hole to copyin from or copyout to?)
3447c478bd9Sstevel@tonic-gate */
3457c478bd9Sstevel@tonic-gate
3467c478bd9Sstevel@tonic-gate if (curthread->t_ontrap != NULL)
3477c478bd9Sstevel@tonic-gate break;
3487c478bd9Sstevel@tonic-gate
3497c478bd9Sstevel@tonic-gate addr = (caddr_t)((uintptr_t)addr & TAGACC_VADDR_MASK);
3507c478bd9Sstevel@tonic-gate if (curthread->t_lofault) {
3517c478bd9Sstevel@tonic-gate if (lodebug) {
3527c478bd9Sstevel@tonic-gate showregs(type, rp, addr, 0);
3537c478bd9Sstevel@tonic-gate traceback((caddr_t)rp->r_sp);
3547c478bd9Sstevel@tonic-gate }
3557c478bd9Sstevel@tonic-gate rp->r_g1 = EFAULT;
3567c478bd9Sstevel@tonic-gate rp->r_pc = curthread->t_lofault;
3577c478bd9Sstevel@tonic-gate rp->r_npc = rp->r_pc + 4;
3587c478bd9Sstevel@tonic-gate goto cleanup;
3597c478bd9Sstevel@tonic-gate }
3607c478bd9Sstevel@tonic-gate (void) die(type, rp, addr, mmu_fsr);
3617c478bd9Sstevel@tonic-gate /*NOTREACHED*/
3627c478bd9Sstevel@tonic-gate
3637c478bd9Sstevel@tonic-gate case FT_PRIV:
3647c478bd9Sstevel@tonic-gate /*
3657c478bd9Sstevel@tonic-gate * This can happen if we access ASI_USER from a kernel
3667c478bd9Sstevel@tonic-gate * thread. To support pxfs, we need to honor lofault if
3677c478bd9Sstevel@tonic-gate * we're doing a copyin/copyout from a kernel thread.
3687c478bd9Sstevel@tonic-gate */
3697c478bd9Sstevel@tonic-gate
3707c478bd9Sstevel@tonic-gate if (nfload(rp, NULL))
3717c478bd9Sstevel@tonic-gate goto cleanup;
3727c478bd9Sstevel@tonic-gate addr = (caddr_t)((uintptr_t)addr & TAGACC_VADDR_MASK);
3737c478bd9Sstevel@tonic-gate if (curthread->t_lofault) {
3747c478bd9Sstevel@tonic-gate if (lodebug) {
3757c478bd9Sstevel@tonic-gate showregs(type, rp, addr, 0);
3767c478bd9Sstevel@tonic-gate traceback((caddr_t)rp->r_sp);
3777c478bd9Sstevel@tonic-gate }
3787c478bd9Sstevel@tonic-gate rp->r_g1 = EFAULT;
3797c478bd9Sstevel@tonic-gate rp->r_pc = curthread->t_lofault;
3807c478bd9Sstevel@tonic-gate rp->r_npc = rp->r_pc + 4;
3817c478bd9Sstevel@tonic-gate goto cleanup;
3827c478bd9Sstevel@tonic-gate }
3837c478bd9Sstevel@tonic-gate (void) die(type, rp, addr, mmu_fsr);
3847c478bd9Sstevel@tonic-gate /*NOTREACHED*/
3857c478bd9Sstevel@tonic-gate
3867c478bd9Sstevel@tonic-gate default:
3877c478bd9Sstevel@tonic-gate if (nfload(rp, NULL))
3887c478bd9Sstevel@tonic-gate goto cleanup;
3897c478bd9Sstevel@tonic-gate addr = (caddr_t)((uintptr_t)addr & TAGACC_VADDR_MASK);
3907c478bd9Sstevel@tonic-gate (void) die(type, rp, addr, mmu_fsr);
3917c478bd9Sstevel@tonic-gate /*NOTREACHED*/
3927c478bd9Sstevel@tonic-gate
3937c478bd9Sstevel@tonic-gate case FT_NFO:
3947c478bd9Sstevel@tonic-gate break;
3957c478bd9Sstevel@tonic-gate }
3967c478bd9Sstevel@tonic-gate /* fall into ... */
3977c478bd9Sstevel@tonic-gate
3987c478bd9Sstevel@tonic-gate case T_DATA_MMU_MISS: /* system data mmu miss */
3997c478bd9Sstevel@tonic-gate case T_DATA_PROT: /* system data protection fault */
4007c478bd9Sstevel@tonic-gate if (nfload(rp, &instr))
4017c478bd9Sstevel@tonic-gate goto cleanup;
4027c478bd9Sstevel@tonic-gate
4037c478bd9Sstevel@tonic-gate /*
4047c478bd9Sstevel@tonic-gate * If we're under on_trap() protection (see <sys/ontrap.h>),
4057c478bd9Sstevel@tonic-gate * set ot_trap and return from the trap to the trampoline.
4067c478bd9Sstevel@tonic-gate */
4077c478bd9Sstevel@tonic-gate if (curthread->t_ontrap != NULL) {
4087c478bd9Sstevel@tonic-gate on_trap_data_t *otp = curthread->t_ontrap;
4097c478bd9Sstevel@tonic-gate
4107c478bd9Sstevel@tonic-gate TRACE_0(TR_FAC_TRAP, TR_C_TRAP_HANDLER_EXIT,
4117c478bd9Sstevel@tonic-gate "C_trap_handler_exit");
4127c478bd9Sstevel@tonic-gate TRACE_0(TR_FAC_TRAP, TR_TRAP_END, "trap_end");
4137c478bd9Sstevel@tonic-gate
4147c478bd9Sstevel@tonic-gate if (otp->ot_prot & OT_DATA_ACCESS) {
4157c478bd9Sstevel@tonic-gate otp->ot_trap |= OT_DATA_ACCESS;
4167c478bd9Sstevel@tonic-gate rp->r_pc = otp->ot_trampoline;
4177c478bd9Sstevel@tonic-gate rp->r_npc = rp->r_pc + 4;
4187c478bd9Sstevel@tonic-gate goto cleanup;
4197c478bd9Sstevel@tonic-gate }
4207c478bd9Sstevel@tonic-gate }
4217c478bd9Sstevel@tonic-gate lofault = curthread->t_lofault;
42269c92249SBryan Cantrill onfault = curthread->t_onfault;
4237c478bd9Sstevel@tonic-gate curthread->t_lofault = 0;
4247c478bd9Sstevel@tonic-gate
4257c478bd9Sstevel@tonic-gate mstate = new_mstate(curthread, LMS_KFAULT);
4267c478bd9Sstevel@tonic-gate
4277c478bd9Sstevel@tonic-gate switch (type) {
4287c478bd9Sstevel@tonic-gate case T_DATA_PROT:
4297c478bd9Sstevel@tonic-gate fault_type = F_PROT;
4307c478bd9Sstevel@tonic-gate rw = S_WRITE;
4317c478bd9Sstevel@tonic-gate break;
4327c478bd9Sstevel@tonic-gate case T_INSTR_MMU_MISS:
4337c478bd9Sstevel@tonic-gate fault_type = F_INVAL;
4347c478bd9Sstevel@tonic-gate rw = S_EXEC;
4357c478bd9Sstevel@tonic-gate break;
4367c478bd9Sstevel@tonic-gate case T_DATA_MMU_MISS:
4377c478bd9Sstevel@tonic-gate case T_DATA_EXCEPTION:
4387c478bd9Sstevel@tonic-gate /*
4397c478bd9Sstevel@tonic-gate * The hardware doesn't update the sfsr on mmu
4407c478bd9Sstevel@tonic-gate * misses so it is not easy to find out whether
4417c478bd9Sstevel@tonic-gate * the access was a read or a write so we need
4427c478bd9Sstevel@tonic-gate * to decode the actual instruction.
4437c478bd9Sstevel@tonic-gate */
4447c478bd9Sstevel@tonic-gate fault_type = F_INVAL;
4457c478bd9Sstevel@tonic-gate rw = get_accesstype(rp);
4467c478bd9Sstevel@tonic-gate break;
4477c478bd9Sstevel@tonic-gate default:
4487c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC, "trap: unknown type %x", type);
4497c478bd9Sstevel@tonic-gate break;
4507c478bd9Sstevel@tonic-gate }
4517c478bd9Sstevel@tonic-gate /*
4527c478bd9Sstevel@tonic-gate * We determine if access was done to kernel or user
4537c478bd9Sstevel@tonic-gate * address space. The addr passed into trap is really the
4547c478bd9Sstevel@tonic-gate * tag access register.
4557c478bd9Sstevel@tonic-gate */
4567c478bd9Sstevel@tonic-gate iskernel = (((uintptr_t)addr & TAGACC_CTX_MASK) == KCONTEXT);
4577c478bd9Sstevel@tonic-gate addr = (caddr_t)((uintptr_t)addr & TAGACC_VADDR_MASK);
4587c478bd9Sstevel@tonic-gate
4597c478bd9Sstevel@tonic-gate res = pagefault(addr, fault_type, rw, iskernel);
4607c478bd9Sstevel@tonic-gate if (!iskernel && res == FC_NOMAP &&
4617c478bd9Sstevel@tonic-gate addr < p->p_usrstack && grow(addr))
4627c478bd9Sstevel@tonic-gate res = 0;
4637c478bd9Sstevel@tonic-gate
4647c478bd9Sstevel@tonic-gate (void) new_mstate(curthread, mstate);
4657c478bd9Sstevel@tonic-gate
4667c478bd9Sstevel@tonic-gate /*
46769c92249SBryan Cantrill * Restore lofault and onfault. If we resolved the fault, exit.
4687c478bd9Sstevel@tonic-gate * If we didn't and lofault wasn't set, die.
4697c478bd9Sstevel@tonic-gate */
4707c478bd9Sstevel@tonic-gate curthread->t_lofault = lofault;
47169c92249SBryan Cantrill curthread->t_onfault = onfault;
4727c478bd9Sstevel@tonic-gate
4737c478bd9Sstevel@tonic-gate if (res == 0)
4747c478bd9Sstevel@tonic-gate goto cleanup;
4757c478bd9Sstevel@tonic-gate
4767c478bd9Sstevel@tonic-gate if (IS_PREFETCH(instr)) {
4777c478bd9Sstevel@tonic-gate /* skip prefetch instructions in kernel-land */
4787c478bd9Sstevel@tonic-gate rp->r_pc = rp->r_npc;
4797c478bd9Sstevel@tonic-gate rp->r_npc += 4;
4807c478bd9Sstevel@tonic-gate goto cleanup;
4817c478bd9Sstevel@tonic-gate }
4827c478bd9Sstevel@tonic-gate
4837c478bd9Sstevel@tonic-gate if ((lofault == 0 || lodebug) &&
4847c478bd9Sstevel@tonic-gate (calc_memaddr(rp, &badaddr) == SIMU_SUCCESS))
4857c478bd9Sstevel@tonic-gate addr = badaddr;
4867c478bd9Sstevel@tonic-gate if (lofault == 0)
4877c478bd9Sstevel@tonic-gate (void) die(type, rp, addr, 0);
4887c478bd9Sstevel@tonic-gate /*
4897c478bd9Sstevel@tonic-gate * Cannot resolve fault. Return to lofault.
4907c478bd9Sstevel@tonic-gate */
4917c478bd9Sstevel@tonic-gate if (lodebug) {
4927c478bd9Sstevel@tonic-gate showregs(type, rp, addr, 0);
4937c478bd9Sstevel@tonic-gate traceback((caddr_t)rp->r_sp);
4947c478bd9Sstevel@tonic-gate }
4957c478bd9Sstevel@tonic-gate if (FC_CODE(res) == FC_OBJERR)
4967c478bd9Sstevel@tonic-gate res = FC_ERRNO(res);
4977c478bd9Sstevel@tonic-gate else
4987c478bd9Sstevel@tonic-gate res = EFAULT;
4997c478bd9Sstevel@tonic-gate rp->r_g1 = res;
5007c478bd9Sstevel@tonic-gate rp->r_pc = curthread->t_lofault;
5017c478bd9Sstevel@tonic-gate rp->r_npc = curthread->t_lofault + 4;
5027c478bd9Sstevel@tonic-gate goto cleanup;
5037c478bd9Sstevel@tonic-gate
5047c478bd9Sstevel@tonic-gate case T_INSTR_EXCEPTION + T_USER: /* user insn access exception */
5057c478bd9Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
5067c478bd9Sstevel@tonic-gate siginfo.si_addr = (caddr_t)rp->r_pc;
5077c478bd9Sstevel@tonic-gate siginfo.si_signo = SIGSEGV;
5087c478bd9Sstevel@tonic-gate siginfo.si_code = X_FAULT_TYPE(mmu_fsr) == FT_PRIV ?
5097c478bd9Sstevel@tonic-gate SEGV_ACCERR : SEGV_MAPERR;
5107c478bd9Sstevel@tonic-gate fault = FLTBOUNDS;
5117c478bd9Sstevel@tonic-gate break;
5127c478bd9Sstevel@tonic-gate
5137c478bd9Sstevel@tonic-gate case T_WIN_OVERFLOW + T_USER: /* window overflow in ??? */
5147c478bd9Sstevel@tonic-gate case T_WIN_UNDERFLOW + T_USER: /* window underflow in ??? */
5157c478bd9Sstevel@tonic-gate case T_SYS_RTT_PAGE + T_USER: /* window underflow in user_rtt */
5167c478bd9Sstevel@tonic-gate case T_INSTR_MMU_MISS + T_USER: /* user instruction mmu miss */
5177c478bd9Sstevel@tonic-gate case T_DATA_MMU_MISS + T_USER: /* user data mmu miss */
5187c478bd9Sstevel@tonic-gate case T_DATA_PROT + T_USER: /* user data protection fault */
5197c478bd9Sstevel@tonic-gate switch (type) {
5207c478bd9Sstevel@tonic-gate case T_INSTR_MMU_MISS + T_USER:
5217c478bd9Sstevel@tonic-gate addr = (caddr_t)rp->r_pc;
5227c478bd9Sstevel@tonic-gate fault_type = F_INVAL;
5237c478bd9Sstevel@tonic-gate rw = S_EXEC;
5247c478bd9Sstevel@tonic-gate break;
5257c478bd9Sstevel@tonic-gate
5267c478bd9Sstevel@tonic-gate case T_DATA_MMU_MISS + T_USER:
5277c478bd9Sstevel@tonic-gate addr = (caddr_t)((uintptr_t)addr & TAGACC_VADDR_MASK);
5287c478bd9Sstevel@tonic-gate fault_type = F_INVAL;
5297c478bd9Sstevel@tonic-gate /*
5307c478bd9Sstevel@tonic-gate * The hardware doesn't update the sfsr on mmu misses
5317c478bd9Sstevel@tonic-gate * so it is not easy to find out whether the access
5327c478bd9Sstevel@tonic-gate * was a read or a write so we need to decode the
5337c478bd9Sstevel@tonic-gate * actual instruction. XXX BUGLY HW
5347c478bd9Sstevel@tonic-gate */
5357c478bd9Sstevel@tonic-gate rw = get_accesstype(rp);
5367c478bd9Sstevel@tonic-gate break;
5377c478bd9Sstevel@tonic-gate
5387c478bd9Sstevel@tonic-gate case T_DATA_PROT + T_USER:
5397c478bd9Sstevel@tonic-gate addr = (caddr_t)((uintptr_t)addr & TAGACC_VADDR_MASK);
5407c478bd9Sstevel@tonic-gate fault_type = F_PROT;
5417c478bd9Sstevel@tonic-gate rw = S_WRITE;
5427c478bd9Sstevel@tonic-gate break;
5437c478bd9Sstevel@tonic-gate
5447c478bd9Sstevel@tonic-gate case T_WIN_OVERFLOW + T_USER:
5457c478bd9Sstevel@tonic-gate addr = (caddr_t)((uintptr_t)addr & TAGACC_VADDR_MASK);
5467c478bd9Sstevel@tonic-gate fault_type = F_INVAL;
5477c478bd9Sstevel@tonic-gate rw = S_WRITE;
5487c478bd9Sstevel@tonic-gate break;
5497c478bd9Sstevel@tonic-gate
5507c478bd9Sstevel@tonic-gate case T_WIN_UNDERFLOW + T_USER:
5517c478bd9Sstevel@tonic-gate case T_SYS_RTT_PAGE + T_USER:
5527c478bd9Sstevel@tonic-gate addr = (caddr_t)((uintptr_t)addr & TAGACC_VADDR_MASK);
5537c478bd9Sstevel@tonic-gate fault_type = F_INVAL;
5547c478bd9Sstevel@tonic-gate rw = S_READ;
5557c478bd9Sstevel@tonic-gate break;
5567c478bd9Sstevel@tonic-gate
5577c478bd9Sstevel@tonic-gate default:
5587c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC, "trap: unknown type %x", type);
5597c478bd9Sstevel@tonic-gate break;
5607c478bd9Sstevel@tonic-gate }
5617c478bd9Sstevel@tonic-gate
5627c478bd9Sstevel@tonic-gate /*
5637c478bd9Sstevel@tonic-gate * If we are single stepping do not call pagefault
5647c478bd9Sstevel@tonic-gate */
5657c478bd9Sstevel@tonic-gate if (stepped) {
5667c478bd9Sstevel@tonic-gate res = FC_NOMAP;
5677c478bd9Sstevel@tonic-gate } else {
5687c478bd9Sstevel@tonic-gate caddr_t vaddr = addr;
5697c478bd9Sstevel@tonic-gate size_t sz;
5707c478bd9Sstevel@tonic-gate int ta;
5717c478bd9Sstevel@tonic-gate
5727c478bd9Sstevel@tonic-gate ASSERT(!(curthread->t_flag & T_WATCHPT));
5737c478bd9Sstevel@tonic-gate watchpage = (pr_watch_active(p) &&
5747c478bd9Sstevel@tonic-gate type != T_WIN_OVERFLOW + T_USER &&
5757c478bd9Sstevel@tonic-gate type != T_WIN_UNDERFLOW + T_USER &&
5767c478bd9Sstevel@tonic-gate type != T_SYS_RTT_PAGE + T_USER &&
5777c478bd9Sstevel@tonic-gate pr_is_watchpage(addr, rw));
5787c478bd9Sstevel@tonic-gate
5797c478bd9Sstevel@tonic-gate if (!watchpage ||
5807c478bd9Sstevel@tonic-gate (sz = instr_size(rp, &vaddr, rw)) <= 0)
5817c478bd9Sstevel@tonic-gate /* EMPTY */;
5827c478bd9Sstevel@tonic-gate else if ((watchcode = pr_is_watchpoint(&vaddr, &ta,
5837c478bd9Sstevel@tonic-gate sz, NULL, rw)) != 0) {
5847c478bd9Sstevel@tonic-gate if (ta) {
5857c478bd9Sstevel@tonic-gate do_watch_step(vaddr, sz, rw,
5867c478bd9Sstevel@tonic-gate watchcode, rp->r_pc);
5877c478bd9Sstevel@tonic-gate fault_type = F_INVAL;
5887c478bd9Sstevel@tonic-gate } else {
5897c478bd9Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
5907c478bd9Sstevel@tonic-gate siginfo.si_signo = SIGTRAP;
5917c478bd9Sstevel@tonic-gate siginfo.si_code = watchcode;
5927c478bd9Sstevel@tonic-gate siginfo.si_addr = vaddr;
5937c478bd9Sstevel@tonic-gate siginfo.si_trapafter = 0;
5947c478bd9Sstevel@tonic-gate siginfo.si_pc = (caddr_t)rp->r_pc;
5957c478bd9Sstevel@tonic-gate fault = FLTWATCH;
5967c478bd9Sstevel@tonic-gate break;
5977c478bd9Sstevel@tonic-gate }
5987c478bd9Sstevel@tonic-gate } else {
5997c478bd9Sstevel@tonic-gate if (rw != S_EXEC &&
6007c478bd9Sstevel@tonic-gate pr_watch_emul(rp, vaddr, rw))
6017c478bd9Sstevel@tonic-gate goto out;
6027c478bd9Sstevel@tonic-gate do_watch_step(vaddr, sz, rw, 0, 0);
6037c478bd9Sstevel@tonic-gate fault_type = F_INVAL;
6047c478bd9Sstevel@tonic-gate }
6057c478bd9Sstevel@tonic-gate
6067c478bd9Sstevel@tonic-gate if (pr_watch_active(p) &&
6077c478bd9Sstevel@tonic-gate (type == T_WIN_OVERFLOW + T_USER ||
6087c478bd9Sstevel@tonic-gate type == T_WIN_UNDERFLOW + T_USER ||
6097c478bd9Sstevel@tonic-gate type == T_SYS_RTT_PAGE + T_USER)) {
6107c478bd9Sstevel@tonic-gate int dotwo = (type == T_WIN_UNDERFLOW + T_USER);
6117c478bd9Sstevel@tonic-gate if (copy_return_window(dotwo))
6127c478bd9Sstevel@tonic-gate goto out;
6137c478bd9Sstevel@tonic-gate fault_type = F_INVAL;
6147c478bd9Sstevel@tonic-gate }
6157c478bd9Sstevel@tonic-gate
6167c478bd9Sstevel@tonic-gate res = pagefault(addr, fault_type, rw, 0);
6177c478bd9Sstevel@tonic-gate
6187c478bd9Sstevel@tonic-gate /*
6197c478bd9Sstevel@tonic-gate * If pagefault succeed, ok.
6207c478bd9Sstevel@tonic-gate * Otherwise grow the stack automatically.
6217c478bd9Sstevel@tonic-gate */
6227c478bd9Sstevel@tonic-gate if (res == 0 ||
6237c478bd9Sstevel@tonic-gate (res == FC_NOMAP &&
6247c478bd9Sstevel@tonic-gate type != T_INSTR_MMU_MISS + T_USER &&
6257c478bd9Sstevel@tonic-gate addr < p->p_usrstack &&
6267c478bd9Sstevel@tonic-gate grow(addr))) {
6277c478bd9Sstevel@tonic-gate int ismem = prismember(&p->p_fltmask, FLTPAGE);
6287c478bd9Sstevel@tonic-gate
6297c478bd9Sstevel@tonic-gate /*
6307c478bd9Sstevel@tonic-gate * instr_size() is used to get the exact
6317c478bd9Sstevel@tonic-gate * address of the fault, instead of the
6327c478bd9Sstevel@tonic-gate * page of the fault. Unfortunately it is
6337c478bd9Sstevel@tonic-gate * very slow, and this is an important
6347c478bd9Sstevel@tonic-gate * code path. Don't call it unless
6357c478bd9Sstevel@tonic-gate * correctness is needed. ie. if FLTPAGE
6367c478bd9Sstevel@tonic-gate * is set, or we're profiling.
6377c478bd9Sstevel@tonic-gate */
6387c478bd9Sstevel@tonic-gate
6397c478bd9Sstevel@tonic-gate if (curthread->t_rprof != NULL || ismem)
6407c478bd9Sstevel@tonic-gate (void) instr_size(rp, &addr, rw);
6417c478bd9Sstevel@tonic-gate
6427c478bd9Sstevel@tonic-gate lwp->lwp_lastfault = FLTPAGE;
6437c478bd9Sstevel@tonic-gate lwp->lwp_lastfaddr = addr;
6447c478bd9Sstevel@tonic-gate
6457c478bd9Sstevel@tonic-gate if (ismem) {
6467c478bd9Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
6477c478bd9Sstevel@tonic-gate siginfo.si_addr = addr;
6487c478bd9Sstevel@tonic-gate (void) stop_on_fault(FLTPAGE, &siginfo);
6497c478bd9Sstevel@tonic-gate }
6507c478bd9Sstevel@tonic-gate goto out;
6517c478bd9Sstevel@tonic-gate }
6527c478bd9Sstevel@tonic-gate
6537c478bd9Sstevel@tonic-gate if (type != (T_INSTR_MMU_MISS + T_USER)) {
6547c478bd9Sstevel@tonic-gate /*
6557c478bd9Sstevel@tonic-gate * check for non-faulting loads, also
6567c478bd9Sstevel@tonic-gate * fetch the instruction to check for
6577c478bd9Sstevel@tonic-gate * flush
6587c478bd9Sstevel@tonic-gate */
6597c478bd9Sstevel@tonic-gate if (nfload(rp, &instr))
6607c478bd9Sstevel@tonic-gate goto out;
6617c478bd9Sstevel@tonic-gate
6627c478bd9Sstevel@tonic-gate /* skip userland prefetch instructions */
6637c478bd9Sstevel@tonic-gate if (IS_PREFETCH(instr)) {
6647c478bd9Sstevel@tonic-gate rp->r_pc = rp->r_npc;
6657c478bd9Sstevel@tonic-gate rp->r_npc += 4;
6667c478bd9Sstevel@tonic-gate goto out;
6677c478bd9Sstevel@tonic-gate /*NOTREACHED*/
6687c478bd9Sstevel@tonic-gate }
6697c478bd9Sstevel@tonic-gate
6707c478bd9Sstevel@tonic-gate /*
6717c478bd9Sstevel@tonic-gate * check if the instruction was a
6727c478bd9Sstevel@tonic-gate * flush. ABI allows users to specify
6737c478bd9Sstevel@tonic-gate * an illegal address on the flush
6747c478bd9Sstevel@tonic-gate * instruction so we simply return in
6757c478bd9Sstevel@tonic-gate * this case.
6767c478bd9Sstevel@tonic-gate *
6777c478bd9Sstevel@tonic-gate * NB: the hardware should set a bit
6787c478bd9Sstevel@tonic-gate * indicating this trap was caused by
6797c478bd9Sstevel@tonic-gate * a flush instruction. Instruction
6807c478bd9Sstevel@tonic-gate * decoding is bugly!
6817c478bd9Sstevel@tonic-gate */
6827c478bd9Sstevel@tonic-gate if (IS_FLUSH(instr)) {
6837c478bd9Sstevel@tonic-gate /* skip the flush instruction */
6847c478bd9Sstevel@tonic-gate rp->r_pc = rp->r_npc;
6857c478bd9Sstevel@tonic-gate rp->r_npc += 4;
6867c478bd9Sstevel@tonic-gate goto out;
6877c478bd9Sstevel@tonic-gate /*NOTREACHED*/
6887c478bd9Sstevel@tonic-gate }
6897c478bd9Sstevel@tonic-gate } else if (res == FC_PROT) {
6907c478bd9Sstevel@tonic-gate report_stack_exec(p, addr);
6917c478bd9Sstevel@tonic-gate }
6927c478bd9Sstevel@tonic-gate
6937c478bd9Sstevel@tonic-gate if (tudebug)
6947c478bd9Sstevel@tonic-gate showregs(type, rp, addr, 0);
6957c478bd9Sstevel@tonic-gate }
6967c478bd9Sstevel@tonic-gate
6977c478bd9Sstevel@tonic-gate /*
6987c478bd9Sstevel@tonic-gate * In the case where both pagefault and grow fail,
6997c478bd9Sstevel@tonic-gate * set the code to the value provided by pagefault.
7007c478bd9Sstevel@tonic-gate */
7017c478bd9Sstevel@tonic-gate (void) instr_size(rp, &addr, rw);
7027c478bd9Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
7037c478bd9Sstevel@tonic-gate siginfo.si_addr = addr;
7047c478bd9Sstevel@tonic-gate if (FC_CODE(res) == FC_OBJERR) {
7057c478bd9Sstevel@tonic-gate siginfo.si_errno = FC_ERRNO(res);
7067c478bd9Sstevel@tonic-gate if (siginfo.si_errno != EINTR) {
7077c478bd9Sstevel@tonic-gate siginfo.si_signo = SIGBUS;
7087c478bd9Sstevel@tonic-gate siginfo.si_code = BUS_OBJERR;
7097c478bd9Sstevel@tonic-gate fault = FLTACCESS;
7107c478bd9Sstevel@tonic-gate }
7117c478bd9Sstevel@tonic-gate } else { /* FC_NOMAP || FC_PROT */
7127c478bd9Sstevel@tonic-gate siginfo.si_signo = SIGSEGV;
7137c478bd9Sstevel@tonic-gate siginfo.si_code = (res == FC_NOMAP) ?
7147c478bd9Sstevel@tonic-gate SEGV_MAPERR : SEGV_ACCERR;
7157c478bd9Sstevel@tonic-gate fault = FLTBOUNDS;
7167c478bd9Sstevel@tonic-gate }
7177c478bd9Sstevel@tonic-gate /*
7187c478bd9Sstevel@tonic-gate * If this is the culmination of a single-step,
7197c478bd9Sstevel@tonic-gate * reset the addr, code, signal and fault to
7207c478bd9Sstevel@tonic-gate * indicate a hardware trace trap.
7217c478bd9Sstevel@tonic-gate */
7227c478bd9Sstevel@tonic-gate if (stepped) {
7237c478bd9Sstevel@tonic-gate pcb_t *pcb = &lwp->lwp_pcb;
7247c478bd9Sstevel@tonic-gate
7257c478bd9Sstevel@tonic-gate siginfo.si_signo = 0;
7267c478bd9Sstevel@tonic-gate fault = 0;
7277c478bd9Sstevel@tonic-gate if (pcb->pcb_step == STEP_WASACTIVE) {
7287c478bd9Sstevel@tonic-gate pcb->pcb_step = STEP_NONE;
7297c478bd9Sstevel@tonic-gate pcb->pcb_tracepc = NULL;
7307c478bd9Sstevel@tonic-gate oldpc = rp->r_pc - 4;
7317c478bd9Sstevel@tonic-gate }
7327c478bd9Sstevel@tonic-gate /*
7337c478bd9Sstevel@tonic-gate * If both NORMAL_STEP and WATCH_STEP are in
7349acbbeafSnn35248 * effect, give precedence to WATCH_STEP.
7357c478bd9Sstevel@tonic-gate * One or the other must be set at this point.
7367c478bd9Sstevel@tonic-gate */
7377c478bd9Sstevel@tonic-gate ASSERT(pcb->pcb_flags & (NORMAL_STEP|WATCH_STEP));
7389acbbeafSnn35248 if ((fault = undo_watch_step(&siginfo)) == 0 &&
7399acbbeafSnn35248 (pcb->pcb_flags & NORMAL_STEP)) {
7407c478bd9Sstevel@tonic-gate siginfo.si_signo = SIGTRAP;
7417c478bd9Sstevel@tonic-gate siginfo.si_code = TRAP_TRACE;
7427c478bd9Sstevel@tonic-gate siginfo.si_addr = (caddr_t)rp->r_pc;
7437c478bd9Sstevel@tonic-gate fault = FLTTRACE;
7447c478bd9Sstevel@tonic-gate }
7457c478bd9Sstevel@tonic-gate pcb->pcb_flags &= ~(NORMAL_STEP|WATCH_STEP);
7467c478bd9Sstevel@tonic-gate }
7477c478bd9Sstevel@tonic-gate break;
7487c478bd9Sstevel@tonic-gate
7497c478bd9Sstevel@tonic-gate case T_DATA_EXCEPTION + T_USER: /* user data access exception */
7507c478bd9Sstevel@tonic-gate
7517c478bd9Sstevel@tonic-gate if (&vis1_partial_support != NULL) {
7527c478bd9Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
7537c478bd9Sstevel@tonic-gate if (vis1_partial_support(rp,
7547c478bd9Sstevel@tonic-gate &siginfo, &fault) == 0)
7557c478bd9Sstevel@tonic-gate goto out;
7567c478bd9Sstevel@tonic-gate }
7577c478bd9Sstevel@tonic-gate
7587c478bd9Sstevel@tonic-gate if (nfload(rp, &instr))
7597c478bd9Sstevel@tonic-gate goto out;
7607c478bd9Sstevel@tonic-gate if (IS_FLUSH(instr)) {
7617c478bd9Sstevel@tonic-gate /* skip the flush instruction */
7627c478bd9Sstevel@tonic-gate rp->r_pc = rp->r_npc;
7637c478bd9Sstevel@tonic-gate rp->r_npc += 4;
7647c478bd9Sstevel@tonic-gate goto out;
7657c478bd9Sstevel@tonic-gate /*NOTREACHED*/
7667c478bd9Sstevel@tonic-gate }
7677c478bd9Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
7687c478bd9Sstevel@tonic-gate siginfo.si_addr = addr;
7697c478bd9Sstevel@tonic-gate switch (X_FAULT_TYPE(mmu_fsr)) {
7707c478bd9Sstevel@tonic-gate case FT_ATOMIC_NC:
7717c478bd9Sstevel@tonic-gate if ((IS_SWAP(instr) && swap_nc(rp, instr)) ||
7727c478bd9Sstevel@tonic-gate (IS_LDSTUB(instr) && ldstub_nc(rp, instr))) {
7737c478bd9Sstevel@tonic-gate /* skip the atomic */
7747c478bd9Sstevel@tonic-gate rp->r_pc = rp->r_npc;
7757c478bd9Sstevel@tonic-gate rp->r_npc += 4;
7767c478bd9Sstevel@tonic-gate goto out;
7777c478bd9Sstevel@tonic-gate }
7787c478bd9Sstevel@tonic-gate /* fall into ... */
7797c478bd9Sstevel@tonic-gate case FT_PRIV:
7807c478bd9Sstevel@tonic-gate siginfo.si_signo = SIGSEGV;
7817c478bd9Sstevel@tonic-gate siginfo.si_code = SEGV_ACCERR;
7827c478bd9Sstevel@tonic-gate fault = FLTBOUNDS;
7837c478bd9Sstevel@tonic-gate break;
7847c478bd9Sstevel@tonic-gate case FT_SPEC_LD:
7857c478bd9Sstevel@tonic-gate case FT_ILL_ALT:
7867c478bd9Sstevel@tonic-gate siginfo.si_signo = SIGILL;
7877c478bd9Sstevel@tonic-gate siginfo.si_code = ILL_ILLADR;
7887c478bd9Sstevel@tonic-gate fault = FLTILL;
7897c478bd9Sstevel@tonic-gate break;
7907c478bd9Sstevel@tonic-gate default:
7917c478bd9Sstevel@tonic-gate siginfo.si_signo = SIGSEGV;
7927c478bd9Sstevel@tonic-gate siginfo.si_code = SEGV_MAPERR;
7937c478bd9Sstevel@tonic-gate fault = FLTBOUNDS;
7947c478bd9Sstevel@tonic-gate break;
7957c478bd9Sstevel@tonic-gate }
7967c478bd9Sstevel@tonic-gate break;
7977c478bd9Sstevel@tonic-gate
7987c478bd9Sstevel@tonic-gate case T_SYS_RTT_ALIGN + T_USER: /* user alignment error */
7997c478bd9Sstevel@tonic-gate case T_ALIGNMENT + T_USER: /* user alignment error */
8007c478bd9Sstevel@tonic-gate if (tudebug)
8017c478bd9Sstevel@tonic-gate showregs(type, rp, addr, 0);
8027c478bd9Sstevel@tonic-gate /*
8037c478bd9Sstevel@tonic-gate * If the user has to do unaligned references
8047c478bd9Sstevel@tonic-gate * the ugly stuff gets done here.
8057c478bd9Sstevel@tonic-gate */
8067c478bd9Sstevel@tonic-gate alignfaults++;
8077c478bd9Sstevel@tonic-gate if (&vis1_partial_support != NULL) {
8087c478bd9Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
8097c478bd9Sstevel@tonic-gate if (vis1_partial_support(rp,
8107c478bd9Sstevel@tonic-gate &siginfo, &fault) == 0)
8117c478bd9Sstevel@tonic-gate goto out;
8127c478bd9Sstevel@tonic-gate }
8137c478bd9Sstevel@tonic-gate
8147c478bd9Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
8157c478bd9Sstevel@tonic-gate if (type == T_SYS_RTT_ALIGN + T_USER) {
816ed7181e6Smb158278 if (nfload(rp, NULL))
817ed7181e6Smb158278 goto out;
8187c478bd9Sstevel@tonic-gate /*
8197c478bd9Sstevel@tonic-gate * Can't do unaligned stack access
8207c478bd9Sstevel@tonic-gate */
8217c478bd9Sstevel@tonic-gate siginfo.si_signo = SIGBUS;
8227c478bd9Sstevel@tonic-gate siginfo.si_code = BUS_ADRALN;
8237c478bd9Sstevel@tonic-gate siginfo.si_addr = addr;
8247c478bd9Sstevel@tonic-gate fault = FLTACCESS;
8257c478bd9Sstevel@tonic-gate break;
8267c478bd9Sstevel@tonic-gate }
827ed7181e6Smb158278
828ed7181e6Smb158278 /*
829ed7181e6Smb158278 * Try to fix alignment before non-faulting load test.
830ed7181e6Smb158278 */
8317c478bd9Sstevel@tonic-gate if (p->p_fixalignment) {
8327c478bd9Sstevel@tonic-gate if (do_unaligned(rp, &badaddr) == SIMU_SUCCESS) {
8337c478bd9Sstevel@tonic-gate rp->r_pc = rp->r_npc;
8347c478bd9Sstevel@tonic-gate rp->r_npc += 4;
8357c478bd9Sstevel@tonic-gate goto out;
8367c478bd9Sstevel@tonic-gate }
837ed7181e6Smb158278 if (nfload(rp, NULL))
838ed7181e6Smb158278 goto out;
8397c478bd9Sstevel@tonic-gate siginfo.si_signo = SIGSEGV;
8407c478bd9Sstevel@tonic-gate siginfo.si_code = SEGV_MAPERR;
8417c478bd9Sstevel@tonic-gate siginfo.si_addr = badaddr;
8427c478bd9Sstevel@tonic-gate fault = FLTBOUNDS;
8437c478bd9Sstevel@tonic-gate } else {
844ed7181e6Smb158278 if (nfload(rp, NULL))
845ed7181e6Smb158278 goto out;
8467c478bd9Sstevel@tonic-gate siginfo.si_signo = SIGBUS;
8477c478bd9Sstevel@tonic-gate siginfo.si_code = BUS_ADRALN;
8487c478bd9Sstevel@tonic-gate if (rp->r_pc & 3) { /* offending address, if pc */
8497c478bd9Sstevel@tonic-gate siginfo.si_addr = (caddr_t)rp->r_pc;
8507c478bd9Sstevel@tonic-gate } else {
8517c478bd9Sstevel@tonic-gate if (calc_memaddr(rp, &badaddr) == SIMU_UNALIGN)
8527c478bd9Sstevel@tonic-gate siginfo.si_addr = badaddr;
8537c478bd9Sstevel@tonic-gate else
8547c478bd9Sstevel@tonic-gate siginfo.si_addr = (caddr_t)rp->r_pc;
8557c478bd9Sstevel@tonic-gate }
8567c478bd9Sstevel@tonic-gate fault = FLTACCESS;
8577c478bd9Sstevel@tonic-gate }
8587c478bd9Sstevel@tonic-gate break;
8597c478bd9Sstevel@tonic-gate
8607c478bd9Sstevel@tonic-gate case T_PRIV_INSTR + T_USER: /* privileged instruction fault */
8617c478bd9Sstevel@tonic-gate if (tudebug)
8627c478bd9Sstevel@tonic-gate showregs(type, rp, (caddr_t)0, 0);
863023e71deSHaik Aftandilian
8647c478bd9Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
865023e71deSHaik Aftandilian #ifdef sun4v
866023e71deSHaik Aftandilian /*
867023e71deSHaik Aftandilian * If this instruction fault is a non-privileged %tick
868023e71deSHaik Aftandilian * or %stick trap, and %tick/%stick user emulation is
869023e71deSHaik Aftandilian * enabled as a result of an OS suspend, then simulate
870023e71deSHaik Aftandilian * the register read. We rely on simulate_rdtick to fail
871023e71deSHaik Aftandilian * if the instruction is not a %tick or %stick read,
872023e71deSHaik Aftandilian * causing us to fall through to the normal privileged
873023e71deSHaik Aftandilian * instruction handling.
874023e71deSHaik Aftandilian */
875023e71deSHaik Aftandilian if (tick_stick_emulation_active &&
876023e71deSHaik Aftandilian (X_FAULT_TYPE(mmu_fsr) == FT_NEW_PRVACT) &&
877023e71deSHaik Aftandilian simulate_rdtick(rp) == SIMU_SUCCESS) {
878023e71deSHaik Aftandilian /* skip the successfully simulated instruction */
879023e71deSHaik Aftandilian rp->r_pc = rp->r_npc;
880023e71deSHaik Aftandilian rp->r_npc += 4;
881023e71deSHaik Aftandilian goto out;
882023e71deSHaik Aftandilian }
883023e71deSHaik Aftandilian #endif
8847c478bd9Sstevel@tonic-gate siginfo.si_signo = SIGILL;
8857c478bd9Sstevel@tonic-gate siginfo.si_code = ILL_PRVOPC;
8867c478bd9Sstevel@tonic-gate siginfo.si_addr = (caddr_t)rp->r_pc;
8877c478bd9Sstevel@tonic-gate fault = FLTILL;
8887c478bd9Sstevel@tonic-gate break;
8897c478bd9Sstevel@tonic-gate
8907c478bd9Sstevel@tonic-gate case T_UNIMP_INSTR: /* priv illegal instruction fault */
8917c478bd9Sstevel@tonic-gate if (fpras_implemented) {
8927c478bd9Sstevel@tonic-gate /*
8937c478bd9Sstevel@tonic-gate * Call fpras_chktrap indicating that
8947c478bd9Sstevel@tonic-gate * we've come from a trap handler and pass
8957c478bd9Sstevel@tonic-gate * the regs. That function may choose to panic
8967c478bd9Sstevel@tonic-gate * (in which case it won't return) or it may
8977c478bd9Sstevel@tonic-gate * determine that a reboot is desired. In the
8987c478bd9Sstevel@tonic-gate * latter case it must alter pc/npc to skip
8997c478bd9Sstevel@tonic-gate * the illegal instruction and continue at
9007c478bd9Sstevel@tonic-gate * a controlled address.
9017c478bd9Sstevel@tonic-gate */
9027c478bd9Sstevel@tonic-gate if (&fpras_chktrap) {
9037c478bd9Sstevel@tonic-gate if (fpras_chktrap(rp))
9047c478bd9Sstevel@tonic-gate goto cleanup;
9057c478bd9Sstevel@tonic-gate }
9067c478bd9Sstevel@tonic-gate }
9077c478bd9Sstevel@tonic-gate #if defined(SF_ERRATA_23) || defined(SF_ERRATA_30) /* call ... illegal-insn */
9087c478bd9Sstevel@tonic-gate instr = *(int *)rp->r_pc;
9097c478bd9Sstevel@tonic-gate if ((instr & 0xc0000000) == 0x40000000) {
9107c478bd9Sstevel@tonic-gate long pc;
9117c478bd9Sstevel@tonic-gate
9127c478bd9Sstevel@tonic-gate rp->r_o7 = (long long)rp->r_pc;
9137c478bd9Sstevel@tonic-gate pc = rp->r_pc + ((instr & 0x3fffffff) << 2);
9147c478bd9Sstevel@tonic-gate rp->r_pc = rp->r_npc;
9157c478bd9Sstevel@tonic-gate rp->r_npc = pc;
9167c478bd9Sstevel@tonic-gate ill_calls++;
9177c478bd9Sstevel@tonic-gate goto cleanup;
9187c478bd9Sstevel@tonic-gate }
9197c478bd9Sstevel@tonic-gate #endif /* SF_ERRATA_23 || SF_ERRATA_30 */
9207c478bd9Sstevel@tonic-gate /*
9217c478bd9Sstevel@tonic-gate * It's not an fpras failure and it's not SF_ERRATA_23 - die
9227c478bd9Sstevel@tonic-gate */
9237c478bd9Sstevel@tonic-gate addr = (caddr_t)rp->r_pc;
9247c478bd9Sstevel@tonic-gate (void) die(type, rp, addr, 0);
9257c478bd9Sstevel@tonic-gate /*NOTREACHED*/
9267c478bd9Sstevel@tonic-gate
9277c478bd9Sstevel@tonic-gate case T_UNIMP_INSTR + T_USER: /* illegal instruction fault */
9287c478bd9Sstevel@tonic-gate #if defined(SF_ERRATA_23) || defined(SF_ERRATA_30) /* call ... illegal-insn */
9297c478bd9Sstevel@tonic-gate instr = fetch_user_instr((caddr_t)rp->r_pc);
9307c478bd9Sstevel@tonic-gate if ((instr & 0xc0000000) == 0x40000000) {
9317c478bd9Sstevel@tonic-gate long pc;
9327c478bd9Sstevel@tonic-gate
9337c478bd9Sstevel@tonic-gate rp->r_o7 = (long long)rp->r_pc;
9347c478bd9Sstevel@tonic-gate pc = rp->r_pc + ((instr & 0x3fffffff) << 2);
9357c478bd9Sstevel@tonic-gate rp->r_pc = rp->r_npc;
9367c478bd9Sstevel@tonic-gate rp->r_npc = pc;
9377c478bd9Sstevel@tonic-gate ill_calls++;
9387c478bd9Sstevel@tonic-gate goto out;
9397c478bd9Sstevel@tonic-gate }
9407c478bd9Sstevel@tonic-gate #endif /* SF_ERRATA_23 || SF_ERRATA_30 */
9417c478bd9Sstevel@tonic-gate if (tudebug)
9427c478bd9Sstevel@tonic-gate showregs(type, rp, (caddr_t)0, 0);
9437c478bd9Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
9447c478bd9Sstevel@tonic-gate /*
9457c478bd9Sstevel@tonic-gate * Try to simulate the instruction.
9467c478bd9Sstevel@tonic-gate */
9477c478bd9Sstevel@tonic-gate switch (simulate_unimp(rp, &badaddr)) {
9487c478bd9Sstevel@tonic-gate case SIMU_RETRY:
9497c478bd9Sstevel@tonic-gate goto out; /* regs are already set up */
9507c478bd9Sstevel@tonic-gate /*NOTREACHED*/
9517c478bd9Sstevel@tonic-gate
9527c478bd9Sstevel@tonic-gate case SIMU_SUCCESS:
9537c478bd9Sstevel@tonic-gate /* skip the successfully simulated instruction */
9547c478bd9Sstevel@tonic-gate rp->r_pc = rp->r_npc;
9557c478bd9Sstevel@tonic-gate rp->r_npc += 4;
9567c478bd9Sstevel@tonic-gate goto out;
9577c478bd9Sstevel@tonic-gate /*NOTREACHED*/
9587c478bd9Sstevel@tonic-gate
9597c478bd9Sstevel@tonic-gate case SIMU_FAULT:
9607c478bd9Sstevel@tonic-gate siginfo.si_signo = SIGSEGV;
9617c478bd9Sstevel@tonic-gate siginfo.si_code = SEGV_MAPERR;
9627c478bd9Sstevel@tonic-gate siginfo.si_addr = badaddr;
9637c478bd9Sstevel@tonic-gate fault = FLTBOUNDS;
9647c478bd9Sstevel@tonic-gate break;
9657c478bd9Sstevel@tonic-gate
9667c478bd9Sstevel@tonic-gate case SIMU_DZERO:
9677c478bd9Sstevel@tonic-gate siginfo.si_signo = SIGFPE;
9687c478bd9Sstevel@tonic-gate siginfo.si_code = FPE_INTDIV;
9697c478bd9Sstevel@tonic-gate siginfo.si_addr = (caddr_t)rp->r_pc;
9707c478bd9Sstevel@tonic-gate fault = FLTIZDIV;
9717c478bd9Sstevel@tonic-gate break;
9727c478bd9Sstevel@tonic-gate
9737c478bd9Sstevel@tonic-gate case SIMU_UNALIGN:
9747c478bd9Sstevel@tonic-gate siginfo.si_signo = SIGBUS;
9757c478bd9Sstevel@tonic-gate siginfo.si_code = BUS_ADRALN;
9767c478bd9Sstevel@tonic-gate siginfo.si_addr = badaddr;
9777c478bd9Sstevel@tonic-gate fault = FLTACCESS;
9787c478bd9Sstevel@tonic-gate break;
9797c478bd9Sstevel@tonic-gate
9807c478bd9Sstevel@tonic-gate case SIMU_ILLEGAL:
9817c478bd9Sstevel@tonic-gate default:
9827c478bd9Sstevel@tonic-gate siginfo.si_signo = SIGILL;
9837c478bd9Sstevel@tonic-gate op3 = (instr >> 19) & 0x3F;
9847c478bd9Sstevel@tonic-gate if ((IS_FLOAT(instr) && (op3 == IOP_V8_STQFA) ||
9857c478bd9Sstevel@tonic-gate (op3 == IOP_V8_STDFA)))
9867c478bd9Sstevel@tonic-gate siginfo.si_code = ILL_ILLADR;
9877c478bd9Sstevel@tonic-gate else
9887c478bd9Sstevel@tonic-gate siginfo.si_code = ILL_ILLOPC;
9897c478bd9Sstevel@tonic-gate siginfo.si_addr = (caddr_t)rp->r_pc;
9907c478bd9Sstevel@tonic-gate fault = FLTILL;
9917c478bd9Sstevel@tonic-gate break;
9927c478bd9Sstevel@tonic-gate }
9937c478bd9Sstevel@tonic-gate break;
9947c478bd9Sstevel@tonic-gate
9954e8a0fa6Swsm case T_UNIMP_LDD + T_USER:
9964e8a0fa6Swsm case T_UNIMP_STD + T_USER:
9974e8a0fa6Swsm if (tudebug)
9984e8a0fa6Swsm showregs(type, rp, (caddr_t)0, 0);
9994e8a0fa6Swsm switch (simulate_lddstd(rp, &badaddr)) {
10004e8a0fa6Swsm case SIMU_SUCCESS:
10014e8a0fa6Swsm /* skip the successfully simulated instruction */
10024e8a0fa6Swsm rp->r_pc = rp->r_npc;
10034e8a0fa6Swsm rp->r_npc += 4;
10044e8a0fa6Swsm goto out;
10054e8a0fa6Swsm /*NOTREACHED*/
10064e8a0fa6Swsm
10074e8a0fa6Swsm case SIMU_FAULT:
10084e8a0fa6Swsm if (nfload(rp, NULL))
10094e8a0fa6Swsm goto out;
10104e8a0fa6Swsm siginfo.si_signo = SIGSEGV;
10114e8a0fa6Swsm siginfo.si_code = SEGV_MAPERR;
10124e8a0fa6Swsm siginfo.si_addr = badaddr;
10134e8a0fa6Swsm fault = FLTBOUNDS;
10144e8a0fa6Swsm break;
10154e8a0fa6Swsm
10164e8a0fa6Swsm case SIMU_UNALIGN:
10174e8a0fa6Swsm if (nfload(rp, NULL))
10184e8a0fa6Swsm goto out;
10194e8a0fa6Swsm siginfo.si_signo = SIGBUS;
10204e8a0fa6Swsm siginfo.si_code = BUS_ADRALN;
10214e8a0fa6Swsm siginfo.si_addr = badaddr;
10224e8a0fa6Swsm fault = FLTACCESS;
10234e8a0fa6Swsm break;
10244e8a0fa6Swsm
10254e8a0fa6Swsm case SIMU_ILLEGAL:
10264e8a0fa6Swsm default:
10274e8a0fa6Swsm siginfo.si_signo = SIGILL;
10284e8a0fa6Swsm siginfo.si_code = ILL_ILLOPC;
10294e8a0fa6Swsm siginfo.si_addr = (caddr_t)rp->r_pc;
10304e8a0fa6Swsm fault = FLTILL;
10314e8a0fa6Swsm break;
10324e8a0fa6Swsm }
10334e8a0fa6Swsm break;
10344e8a0fa6Swsm
10354e8a0fa6Swsm case T_UNIMP_LDD:
10364e8a0fa6Swsm case T_UNIMP_STD:
10374e8a0fa6Swsm if (simulate_lddstd(rp, &badaddr) == SIMU_SUCCESS) {
10384e8a0fa6Swsm /* skip the successfully simulated instruction */
10394e8a0fa6Swsm rp->r_pc = rp->r_npc;
10404e8a0fa6Swsm rp->r_npc += 4;
10414e8a0fa6Swsm goto cleanup;
10424e8a0fa6Swsm /*NOTREACHED*/
10434e8a0fa6Swsm }
10444e8a0fa6Swsm /*
10454e8a0fa6Swsm * A third party driver executed an {LDD,STD,LDDA,STDA}
10464e8a0fa6Swsm * that we couldn't simulate.
10474e8a0fa6Swsm */
10484e8a0fa6Swsm if (nfload(rp, NULL))
10494e8a0fa6Swsm goto cleanup;
10504e8a0fa6Swsm
10514e8a0fa6Swsm if (curthread->t_lofault) {
10524e8a0fa6Swsm if (lodebug) {
10534e8a0fa6Swsm showregs(type, rp, addr, 0);
10544e8a0fa6Swsm traceback((caddr_t)rp->r_sp);
10554e8a0fa6Swsm }
10564e8a0fa6Swsm rp->r_g1 = EFAULT;
10574e8a0fa6Swsm rp->r_pc = curthread->t_lofault;
10584e8a0fa6Swsm rp->r_npc = rp->r_pc + 4;
10594e8a0fa6Swsm goto cleanup;
10604e8a0fa6Swsm }
10614e8a0fa6Swsm (void) die(type, rp, addr, 0);
10624e8a0fa6Swsm /*NOTREACHED*/
10634e8a0fa6Swsm
10647c478bd9Sstevel@tonic-gate case T_IDIV0 + T_USER: /* integer divide by zero */
10657c478bd9Sstevel@tonic-gate case T_DIV0 + T_USER: /* integer divide by zero */
10667c478bd9Sstevel@tonic-gate if (tudebug && tudebugfpe)
10677c478bd9Sstevel@tonic-gate showregs(type, rp, (caddr_t)0, 0);
10687c478bd9Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
10697c478bd9Sstevel@tonic-gate siginfo.si_signo = SIGFPE;
10707c478bd9Sstevel@tonic-gate siginfo.si_code = FPE_INTDIV;
10717c478bd9Sstevel@tonic-gate siginfo.si_addr = (caddr_t)rp->r_pc;
10727c478bd9Sstevel@tonic-gate fault = FLTIZDIV;
10737c478bd9Sstevel@tonic-gate break;
10747c478bd9Sstevel@tonic-gate
10757c478bd9Sstevel@tonic-gate case T_INT_OVERFLOW + T_USER: /* integer overflow */
10767c478bd9Sstevel@tonic-gate if (tudebug && tudebugfpe)
10777c478bd9Sstevel@tonic-gate showregs(type, rp, (caddr_t)0, 0);
10787c478bd9Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
10797c478bd9Sstevel@tonic-gate siginfo.si_signo = SIGFPE;
10807c478bd9Sstevel@tonic-gate siginfo.si_code = FPE_INTOVF;
10817c478bd9Sstevel@tonic-gate siginfo.si_addr = (caddr_t)rp->r_pc;
10827c478bd9Sstevel@tonic-gate fault = FLTIOVF;
10837c478bd9Sstevel@tonic-gate break;
10847c478bd9Sstevel@tonic-gate
10857c478bd9Sstevel@tonic-gate case T_BREAKPOINT + T_USER: /* breakpoint trap (t 1) */
10867c478bd9Sstevel@tonic-gate if (tudebug && tudebugbpt)
10877c478bd9Sstevel@tonic-gate showregs(type, rp, (caddr_t)0, 0);
10887c478bd9Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
10897c478bd9Sstevel@tonic-gate siginfo.si_signo = SIGTRAP;
10907c478bd9Sstevel@tonic-gate siginfo.si_code = TRAP_BRKPT;
10917c478bd9Sstevel@tonic-gate siginfo.si_addr = (caddr_t)rp->r_pc;
10927c478bd9Sstevel@tonic-gate fault = FLTBPT;
10937c478bd9Sstevel@tonic-gate break;
10947c478bd9Sstevel@tonic-gate
10957c478bd9Sstevel@tonic-gate case T_TAG_OVERFLOW + T_USER: /* tag overflow (taddcctv, tsubcctv) */
10967c478bd9Sstevel@tonic-gate if (tudebug)
10977c478bd9Sstevel@tonic-gate showregs(type, rp, (caddr_t)0, 0);
10987c478bd9Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
10997c478bd9Sstevel@tonic-gate siginfo.si_signo = SIGEMT;
11007c478bd9Sstevel@tonic-gate siginfo.si_code = EMT_TAGOVF;
11017c478bd9Sstevel@tonic-gate siginfo.si_addr = (caddr_t)rp->r_pc;
11027c478bd9Sstevel@tonic-gate fault = FLTACCESS;
11037c478bd9Sstevel@tonic-gate break;
11047c478bd9Sstevel@tonic-gate
11057c478bd9Sstevel@tonic-gate case T_FLUSH_PCB + T_USER: /* finish user window overflow */
11067c478bd9Sstevel@tonic-gate case T_FLUSHW + T_USER: /* finish user window flush */
11077c478bd9Sstevel@tonic-gate /*
11087c478bd9Sstevel@tonic-gate * This trap is entered from sys_rtt in locore.s when,
11097c478bd9Sstevel@tonic-gate * upon return to user is is found that there are user
11107c478bd9Sstevel@tonic-gate * windows in pcb_wbuf. This happens because they could
11117c478bd9Sstevel@tonic-gate * not be saved on the user stack, either because it
11127c478bd9Sstevel@tonic-gate * wasn't resident or because it was misaligned.
11137c478bd9Sstevel@tonic-gate */
11147c478bd9Sstevel@tonic-gate {
11157c478bd9Sstevel@tonic-gate int error;
11167c478bd9Sstevel@tonic-gate caddr_t sp;
11177c478bd9Sstevel@tonic-gate
11187c478bd9Sstevel@tonic-gate error = flush_user_windows_to_stack(&sp);
11197c478bd9Sstevel@tonic-gate /*
11207c478bd9Sstevel@tonic-gate * Possible errors:
11217c478bd9Sstevel@tonic-gate * error copying out
11227c478bd9Sstevel@tonic-gate * unaligned stack pointer
11237c478bd9Sstevel@tonic-gate * The first is given to us as the return value
11247c478bd9Sstevel@tonic-gate * from flush_user_windows_to_stack(). The second
11257c478bd9Sstevel@tonic-gate * results in residual windows in the pcb.
11267c478bd9Sstevel@tonic-gate */
11277c478bd9Sstevel@tonic-gate if (error != 0) {
11287c478bd9Sstevel@tonic-gate /*
11297c478bd9Sstevel@tonic-gate * EINTR comes from a signal during copyout;
11307c478bd9Sstevel@tonic-gate * we should not post another signal.
11317c478bd9Sstevel@tonic-gate */
11327c478bd9Sstevel@tonic-gate if (error != EINTR) {
11337c478bd9Sstevel@tonic-gate /*
11347c478bd9Sstevel@tonic-gate * Zap the process with a SIGSEGV - process
11357c478bd9Sstevel@tonic-gate * may be managing its own stack growth by
11367c478bd9Sstevel@tonic-gate * taking SIGSEGVs on a different signal stack.
11377c478bd9Sstevel@tonic-gate */
11387c478bd9Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
11397c478bd9Sstevel@tonic-gate siginfo.si_signo = SIGSEGV;
11407c478bd9Sstevel@tonic-gate siginfo.si_code = SEGV_MAPERR;
11417c478bd9Sstevel@tonic-gate siginfo.si_addr = sp;
11427c478bd9Sstevel@tonic-gate fault = FLTBOUNDS;
11437c478bd9Sstevel@tonic-gate }
11447c478bd9Sstevel@tonic-gate break;
11457c478bd9Sstevel@tonic-gate } else if (mpcb->mpcb_wbcnt) {
11467c478bd9Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
11477c478bd9Sstevel@tonic-gate siginfo.si_signo = SIGILL;
11487c478bd9Sstevel@tonic-gate siginfo.si_code = ILL_BADSTK;
11497c478bd9Sstevel@tonic-gate siginfo.si_addr = (caddr_t)rp->r_pc;
11507c478bd9Sstevel@tonic-gate fault = FLTILL;
11517c478bd9Sstevel@tonic-gate break;
11527c478bd9Sstevel@tonic-gate }
11537c478bd9Sstevel@tonic-gate }
11547c478bd9Sstevel@tonic-gate
11557c478bd9Sstevel@tonic-gate /*
11567c478bd9Sstevel@tonic-gate * T_FLUSHW is used when handling a ta 0x3 -- the old flush
11577c478bd9Sstevel@tonic-gate * window trap -- which is implemented by executing the
11587c478bd9Sstevel@tonic-gate * flushw instruction. The flushw can trap if any of the
11597c478bd9Sstevel@tonic-gate * stack pages are not writable for whatever reason. In this
11607c478bd9Sstevel@tonic-gate * case only, we advance the pc to the next instruction so
11617c478bd9Sstevel@tonic-gate * that the user thread doesn't needlessly execute the trap
11627c478bd9Sstevel@tonic-gate * again. Normally this wouldn't be a problem -- we'll
11637c478bd9Sstevel@tonic-gate * usually only end up here if this is the first touch to a
11647c478bd9Sstevel@tonic-gate * stack page -- since the second execution won't trap, but
11657c478bd9Sstevel@tonic-gate * if there's a watchpoint on the stack page the user thread
11667c478bd9Sstevel@tonic-gate * would spin, continuously executing the trap instruction.
11677c478bd9Sstevel@tonic-gate */
11687c478bd9Sstevel@tonic-gate if (type == T_FLUSHW + T_USER) {
11697c478bd9Sstevel@tonic-gate rp->r_pc = rp->r_npc;
11707c478bd9Sstevel@tonic-gate rp->r_npc += 4;
11717c478bd9Sstevel@tonic-gate }
11727c478bd9Sstevel@tonic-gate goto out;
11737c478bd9Sstevel@tonic-gate
11747c478bd9Sstevel@tonic-gate case T_AST + T_USER: /* profiling or resched pseudo trap */
11757c478bd9Sstevel@tonic-gate if (lwp->lwp_pcb.pcb_flags & CPC_OVERFLOW) {
11767c478bd9Sstevel@tonic-gate lwp->lwp_pcb.pcb_flags &= ~CPC_OVERFLOW;
11777c478bd9Sstevel@tonic-gate if (kcpc_overflow_ast()) {
11787c478bd9Sstevel@tonic-gate /*
11797c478bd9Sstevel@tonic-gate * Signal performance counter overflow
11807c478bd9Sstevel@tonic-gate */
11817c478bd9Sstevel@tonic-gate if (tudebug)
11827c478bd9Sstevel@tonic-gate showregs(type, rp, (caddr_t)0, 0);
11837c478bd9Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
11847c478bd9Sstevel@tonic-gate siginfo.si_signo = SIGEMT;
11857c478bd9Sstevel@tonic-gate siginfo.si_code = EMT_CPCOVF;
11867c478bd9Sstevel@tonic-gate siginfo.si_addr = (caddr_t)rp->r_pc;
11877c478bd9Sstevel@tonic-gate /* for trap_cleanup(), below */
11887c478bd9Sstevel@tonic-gate oldpc = rp->r_pc - 4;
11897c478bd9Sstevel@tonic-gate fault = FLTCPCOVF;
11907c478bd9Sstevel@tonic-gate }
11917c478bd9Sstevel@tonic-gate }
11927c478bd9Sstevel@tonic-gate
11937c478bd9Sstevel@tonic-gate /*
11947c478bd9Sstevel@tonic-gate * The CPC_OVERFLOW check above may already have populated
11957c478bd9Sstevel@tonic-gate * siginfo and set fault, so the checks below must not
11967c478bd9Sstevel@tonic-gate * touch these and the functions they call must use
11977c478bd9Sstevel@tonic-gate * trapsig() directly.
11987c478bd9Sstevel@tonic-gate */
11997c478bd9Sstevel@tonic-gate
12007c478bd9Sstevel@tonic-gate if (lwp->lwp_pcb.pcb_flags & ASYNC_HWERR) {
12017c478bd9Sstevel@tonic-gate lwp->lwp_pcb.pcb_flags &= ~ASYNC_HWERR;
12027c478bd9Sstevel@tonic-gate trap_async_hwerr();
12037c478bd9Sstevel@tonic-gate }
12047c478bd9Sstevel@tonic-gate
12057c478bd9Sstevel@tonic-gate if (lwp->lwp_pcb.pcb_flags & ASYNC_BERR) {
12067c478bd9Sstevel@tonic-gate lwp->lwp_pcb.pcb_flags &= ~ASYNC_BERR;
12077c478bd9Sstevel@tonic-gate trap_async_berr_bto(ASYNC_BERR, rp);
12087c478bd9Sstevel@tonic-gate }
12097c478bd9Sstevel@tonic-gate
12107c478bd9Sstevel@tonic-gate if (lwp->lwp_pcb.pcb_flags & ASYNC_BTO) {
12117c478bd9Sstevel@tonic-gate lwp->lwp_pcb.pcb_flags &= ~ASYNC_BTO;
12127c478bd9Sstevel@tonic-gate trap_async_berr_bto(ASYNC_BTO, rp);
12137c478bd9Sstevel@tonic-gate }
12147c478bd9Sstevel@tonic-gate
12157c478bd9Sstevel@tonic-gate break;
12167c478bd9Sstevel@tonic-gate }
12177c478bd9Sstevel@tonic-gate
121810e812d4Saf if (fault) {
121910e812d4Saf /* We took a fault so abort single step. */
122010e812d4Saf lwp->lwp_pcb.pcb_flags &= ~(NORMAL_STEP|WATCH_STEP);
122110e812d4Saf }
12227c478bd9Sstevel@tonic-gate trap_cleanup(rp, fault, &siginfo, oldpc == rp->r_pc);
12237c478bd9Sstevel@tonic-gate
12247c478bd9Sstevel@tonic-gate out: /* We can't get here from a system trap */
12257c478bd9Sstevel@tonic-gate ASSERT(type & T_USER);
12267c478bd9Sstevel@tonic-gate trap_rtt();
12277c478bd9Sstevel@tonic-gate (void) new_mstate(curthread, mstate);
12287c478bd9Sstevel@tonic-gate /* Kernel probe */
12297c478bd9Sstevel@tonic-gate TNF_PROBE_1(thread_state, "thread", /* CSTYLED */,
12307c478bd9Sstevel@tonic-gate tnf_microstate, state, LMS_USER);
12317c478bd9Sstevel@tonic-gate
12327c478bd9Sstevel@tonic-gate TRACE_0(TR_FAC_TRAP, TR_C_TRAP_HANDLER_EXIT, "C_trap_handler_exit");
12337c478bd9Sstevel@tonic-gate return;
12347c478bd9Sstevel@tonic-gate
12357c478bd9Sstevel@tonic-gate cleanup: /* system traps end up here */
12367c478bd9Sstevel@tonic-gate ASSERT(!(type & T_USER));
12377c478bd9Sstevel@tonic-gate
12387c478bd9Sstevel@tonic-gate TRACE_0(TR_FAC_TRAP, TR_C_TRAP_HANDLER_EXIT, "C_trap_handler_exit");
12397c478bd9Sstevel@tonic-gate }
12407c478bd9Sstevel@tonic-gate
12417c478bd9Sstevel@tonic-gate void
trap_cleanup(struct regs * rp,uint_t fault,k_siginfo_t * sip,int restartable)12427c478bd9Sstevel@tonic-gate trap_cleanup(
12437c478bd9Sstevel@tonic-gate struct regs *rp,
12447c478bd9Sstevel@tonic-gate uint_t fault,
12457c478bd9Sstevel@tonic-gate k_siginfo_t *sip,
12467c478bd9Sstevel@tonic-gate int restartable)
12477c478bd9Sstevel@tonic-gate {
12487c478bd9Sstevel@tonic-gate extern void aio_cleanup();
12497c478bd9Sstevel@tonic-gate proc_t *p = ttoproc(curthread);
12507c478bd9Sstevel@tonic-gate klwp_id_t lwp = ttolwp(curthread);
12517c478bd9Sstevel@tonic-gate
12527c478bd9Sstevel@tonic-gate if (fault) {
12537c478bd9Sstevel@tonic-gate /*
12547c478bd9Sstevel@tonic-gate * Remember the fault and fault address
12557c478bd9Sstevel@tonic-gate * for real-time (SIGPROF) profiling.
12567c478bd9Sstevel@tonic-gate */
12577c478bd9Sstevel@tonic-gate lwp->lwp_lastfault = fault;
12587c478bd9Sstevel@tonic-gate lwp->lwp_lastfaddr = sip->si_addr;
12597c478bd9Sstevel@tonic-gate
12607c478bd9Sstevel@tonic-gate DTRACE_PROC2(fault, int, fault, ksiginfo_t *, sip);
12617c478bd9Sstevel@tonic-gate
12627c478bd9Sstevel@tonic-gate /*
12637c478bd9Sstevel@tonic-gate * If a debugger has declared this fault to be an
12647c478bd9Sstevel@tonic-gate * event of interest, stop the lwp. Otherwise just
12657c478bd9Sstevel@tonic-gate * deliver the associated signal.
12667c478bd9Sstevel@tonic-gate */
12677c478bd9Sstevel@tonic-gate if (sip->si_signo != SIGKILL &&
12687c478bd9Sstevel@tonic-gate prismember(&p->p_fltmask, fault) &&
12697c478bd9Sstevel@tonic-gate stop_on_fault(fault, sip) == 0)
12707c478bd9Sstevel@tonic-gate sip->si_signo = 0;
12717c478bd9Sstevel@tonic-gate }
12727c478bd9Sstevel@tonic-gate
12737c478bd9Sstevel@tonic-gate if (sip->si_signo)
12747c478bd9Sstevel@tonic-gate trapsig(sip, restartable);
12757c478bd9Sstevel@tonic-gate
12767c478bd9Sstevel@tonic-gate if (lwp->lwp_oweupc)
12777c478bd9Sstevel@tonic-gate profil_tick(rp->r_pc);
12787c478bd9Sstevel@tonic-gate
12797c478bd9Sstevel@tonic-gate if (curthread->t_astflag | curthread->t_sig_check) {
12807c478bd9Sstevel@tonic-gate /*
12817c478bd9Sstevel@tonic-gate * Turn off the AST flag before checking all the conditions that
12827c478bd9Sstevel@tonic-gate * may have caused an AST. This flag is on whenever a signal or
12837c478bd9Sstevel@tonic-gate * unusual condition should be handled after the next trap or
12847c478bd9Sstevel@tonic-gate * syscall.
12857c478bd9Sstevel@tonic-gate */
12867c478bd9Sstevel@tonic-gate astoff(curthread);
12877c478bd9Sstevel@tonic-gate curthread->t_sig_check = 0;
12887c478bd9Sstevel@tonic-gate
1289efd37614Sdv142724 /*
1290efd37614Sdv142724 * The following check is legal for the following reasons:
1291efd37614Sdv142724 * 1) The thread we are checking, is ourselves, so there is
1292efd37614Sdv142724 * no way the proc can go away.
1293efd37614Sdv142724 * 2) The only time we need to be protected by the
1294efd37614Sdv142724 * lock is if the binding is changed.
1295efd37614Sdv142724 *
1296efd37614Sdv142724 * Note we will still take the lock and check the binding
1297efd37614Sdv142724 * if the condition was true without the lock held. This
1298efd37614Sdv142724 * prevents lock contention among threads owned by the
1299efd37614Sdv142724 * same proc.
1300efd37614Sdv142724 */
1301efd37614Sdv142724
1302efd37614Sdv142724 if (curthread->t_proc_flag & TP_CHANGEBIND) {
13037c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
13047c478bd9Sstevel@tonic-gate if (curthread->t_proc_flag & TP_CHANGEBIND) {
13057c478bd9Sstevel@tonic-gate timer_lwpbind();
13067c478bd9Sstevel@tonic-gate curthread->t_proc_flag &= ~TP_CHANGEBIND;
13077c478bd9Sstevel@tonic-gate }
13087c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
1309efd37614Sdv142724 }
13107c478bd9Sstevel@tonic-gate
13117c478bd9Sstevel@tonic-gate /*
13127c478bd9Sstevel@tonic-gate * for kaio requests that are on the per-process poll queue,
13137c478bd9Sstevel@tonic-gate * aiop->aio_pollq, they're AIO_POLL bit is set, the kernel
13147c478bd9Sstevel@tonic-gate * should copyout their result_t to user memory. by copying
13157c478bd9Sstevel@tonic-gate * out the result_t, the user can poll on memory waiting
13167c478bd9Sstevel@tonic-gate * for the kaio request to complete.
13177c478bd9Sstevel@tonic-gate */
13187c478bd9Sstevel@tonic-gate if (p->p_aio)
13197c478bd9Sstevel@tonic-gate aio_cleanup(0);
13207c478bd9Sstevel@tonic-gate
13217c478bd9Sstevel@tonic-gate /*
13227c478bd9Sstevel@tonic-gate * If this LWP was asked to hold, call holdlwp(), which will
13237c478bd9Sstevel@tonic-gate * stop. holdlwps() sets this up and calls pokelwps() which
13247c478bd9Sstevel@tonic-gate * sets the AST flag.
13257c478bd9Sstevel@tonic-gate *
13267c478bd9Sstevel@tonic-gate * Also check TP_EXITLWP, since this is used by fresh new LWPs
13277c478bd9Sstevel@tonic-gate * through lwp_rtt(). That flag is set if the lwp_create(2)
13287c478bd9Sstevel@tonic-gate * syscall failed after creating the LWP.
13297c478bd9Sstevel@tonic-gate */
13307c478bd9Sstevel@tonic-gate if (ISHOLD(p))
13317c478bd9Sstevel@tonic-gate holdlwp();
13327c478bd9Sstevel@tonic-gate
13337c478bd9Sstevel@tonic-gate /*
13347c478bd9Sstevel@tonic-gate * All code that sets signals and makes ISSIG evaluate true must
13357c478bd9Sstevel@tonic-gate * set t_astflag afterwards.
13367c478bd9Sstevel@tonic-gate */
13377c478bd9Sstevel@tonic-gate if (ISSIG_PENDING(curthread, lwp, p)) {
13387c478bd9Sstevel@tonic-gate if (issig(FORREAL))
13397c478bd9Sstevel@tonic-gate psig();
13407c478bd9Sstevel@tonic-gate curthread->t_sig_check = 1;
13417c478bd9Sstevel@tonic-gate }
13427c478bd9Sstevel@tonic-gate
13437c478bd9Sstevel@tonic-gate if (curthread->t_rprof != NULL) {
1344e0cf54a5SRoger A. Faulkner realsigprof(0, 0, 0);
13457c478bd9Sstevel@tonic-gate curthread->t_sig_check = 1;
13467c478bd9Sstevel@tonic-gate }
13477c478bd9Sstevel@tonic-gate }
13487c478bd9Sstevel@tonic-gate }
13497c478bd9Sstevel@tonic-gate
13507c478bd9Sstevel@tonic-gate /*
13517c478bd9Sstevel@tonic-gate * Called from fp_traps when a floating point trap occurs.
13527c478bd9Sstevel@tonic-gate * Note that the T_DATA_EXCEPTION case does not use X_FAULT_TYPE(mmu_fsr),
13537c478bd9Sstevel@tonic-gate * because mmu_fsr (now changed to code) is always 0.
13547c478bd9Sstevel@tonic-gate * Note that the T_UNIMP_INSTR case does not call simulate_unimp(),
13557c478bd9Sstevel@tonic-gate * because the simulator only simulates multiply and divide instructions,
13567c478bd9Sstevel@tonic-gate * which would not cause floating point traps in the first place.
13577c478bd9Sstevel@tonic-gate * XXX - Supervisor mode floating point traps?
13587c478bd9Sstevel@tonic-gate */
13597c478bd9Sstevel@tonic-gate void
fpu_trap(struct regs * rp,caddr_t addr,uint32_t type,uint32_t code)13607c478bd9Sstevel@tonic-gate fpu_trap(struct regs *rp, caddr_t addr, uint32_t type, uint32_t code)
13617c478bd9Sstevel@tonic-gate {
13627c478bd9Sstevel@tonic-gate proc_t *p = ttoproc(curthread);
13637c478bd9Sstevel@tonic-gate klwp_id_t lwp = ttolwp(curthread);
13647c478bd9Sstevel@tonic-gate k_siginfo_t siginfo;
13657c478bd9Sstevel@tonic-gate uint_t op3, fault = 0;
13667c478bd9Sstevel@tonic-gate int mstate;
13677c478bd9Sstevel@tonic-gate char *badaddr;
13687c478bd9Sstevel@tonic-gate kfpu_t *fp;
1369*bc0e9132SGordon Ross struct _fpq *pfpq;
13707c478bd9Sstevel@tonic-gate uint32_t inst;
13717c478bd9Sstevel@tonic-gate utrap_handler_t *utrapp;
13727c478bd9Sstevel@tonic-gate
13737c478bd9Sstevel@tonic-gate CPU_STATS_ADDQ(CPU, sys, trap, 1);
13747c478bd9Sstevel@tonic-gate
13757c478bd9Sstevel@tonic-gate ASSERT(curthread->t_schedflag & TS_DONT_SWAP);
13767c478bd9Sstevel@tonic-gate
13777c478bd9Sstevel@tonic-gate if (USERMODE(rp->r_tstate)) {
13787c478bd9Sstevel@tonic-gate /*
13797c478bd9Sstevel@tonic-gate * Set lwp_state before trying to acquire any
13807c478bd9Sstevel@tonic-gate * adaptive lock
13817c478bd9Sstevel@tonic-gate */
13827c478bd9Sstevel@tonic-gate ASSERT(lwp != NULL);
13837c478bd9Sstevel@tonic-gate lwp->lwp_state = LWP_SYS;
13847c478bd9Sstevel@tonic-gate /*
13857c478bd9Sstevel@tonic-gate * Set up the current cred to use during this trap. u_cred
13867c478bd9Sstevel@tonic-gate * no longer exists. t_cred is used instead.
13877c478bd9Sstevel@tonic-gate * The current process credential applies to the thread for
13887c478bd9Sstevel@tonic-gate * the entire trap. If trapping from the kernel, this
13897c478bd9Sstevel@tonic-gate * should already be set up.
13907c478bd9Sstevel@tonic-gate */
13917c478bd9Sstevel@tonic-gate if (curthread->t_cred != p->p_cred) {
13927c478bd9Sstevel@tonic-gate cred_t *oldcred = curthread->t_cred;
13937c478bd9Sstevel@tonic-gate /*
13947c478bd9Sstevel@tonic-gate * DTrace accesses t_cred in probe context. t_cred
13957c478bd9Sstevel@tonic-gate * must always be either NULL, or point to a valid,
13967c478bd9Sstevel@tonic-gate * allocated cred structure.
13977c478bd9Sstevel@tonic-gate */
13987c478bd9Sstevel@tonic-gate curthread->t_cred = crgetcred();
13997c478bd9Sstevel@tonic-gate crfree(oldcred);
14007c478bd9Sstevel@tonic-gate }
14017c478bd9Sstevel@tonic-gate ASSERT(lwp->lwp_regs == rp);
14027c478bd9Sstevel@tonic-gate mstate = new_mstate(curthread, LMS_TRAP);
14037c478bd9Sstevel@tonic-gate siginfo.si_signo = 0;
14047c478bd9Sstevel@tonic-gate type |= T_USER;
14057c478bd9Sstevel@tonic-gate }
14067c478bd9Sstevel@tonic-gate
14077c478bd9Sstevel@tonic-gate TRACE_1(TR_FAC_TRAP, TR_C_TRAP_HANDLER_ENTER,
14087c478bd9Sstevel@tonic-gate "C_fpu_trap_handler_enter:type %x", type);
14097c478bd9Sstevel@tonic-gate
14107c478bd9Sstevel@tonic-gate if (tudebug && tudebugfpe)
14117c478bd9Sstevel@tonic-gate showregs(type, rp, addr, 0);
14127c478bd9Sstevel@tonic-gate
14137c478bd9Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
14147c478bd9Sstevel@tonic-gate siginfo.si_code = code;
14157c478bd9Sstevel@tonic-gate siginfo.si_addr = addr;
14167c478bd9Sstevel@tonic-gate
14177c478bd9Sstevel@tonic-gate switch (type) {
14187c478bd9Sstevel@tonic-gate
14197c478bd9Sstevel@tonic-gate case T_FP_EXCEPTION_IEEE + T_USER: /* FPU arithmetic exception */
14207c478bd9Sstevel@tonic-gate /*
14217c478bd9Sstevel@tonic-gate * FPU arithmetic exception - fake up a fpq if we
14227c478bd9Sstevel@tonic-gate * came here directly from _fp_ieee_exception,
14237c478bd9Sstevel@tonic-gate * which is indicated by a zero fpu_qcnt.
14247c478bd9Sstevel@tonic-gate */
14257c478bd9Sstevel@tonic-gate fp = lwptofpu(curthread->t_lwp);
14267c478bd9Sstevel@tonic-gate utrapp = curthread->t_procp->p_utraps;
14277c478bd9Sstevel@tonic-gate if (fp->fpu_qcnt == 0) {
14287c478bd9Sstevel@tonic-gate inst = fetch_user_instr((caddr_t)rp->r_pc);
14297c478bd9Sstevel@tonic-gate lwp->lwp_state = LWP_SYS;
14307c478bd9Sstevel@tonic-gate pfpq = &fp->fpu_q->FQu.fpq;
14317c478bd9Sstevel@tonic-gate pfpq->fpq_addr = (uint32_t *)rp->r_pc;
14327c478bd9Sstevel@tonic-gate pfpq->fpq_instr = inst;
14337c478bd9Sstevel@tonic-gate fp->fpu_qcnt = 1;
1434*bc0e9132SGordon Ross fp->fpu_q_entrysize = sizeof (struct _fpq);
14357c478bd9Sstevel@tonic-gate #ifdef SF_V9_TABLE_28
14367c478bd9Sstevel@tonic-gate /*
14377c478bd9Sstevel@tonic-gate * Spitfire and blackbird followed the SPARC V9 manual
14387c478bd9Sstevel@tonic-gate * paragraph 3 of section 5.1.7.9 FSR_current_exception
14397c478bd9Sstevel@tonic-gate * (cexc) for setting fsr.cexc bits on underflow and
14407c478bd9Sstevel@tonic-gate * overflow traps when the fsr.tem.inexact bit is set,
14417c478bd9Sstevel@tonic-gate * instead of following Table 28. Bugid 1263234.
14427c478bd9Sstevel@tonic-gate */
14437c478bd9Sstevel@tonic-gate {
14447c478bd9Sstevel@tonic-gate extern int spitfire_bb_fsr_bug;
14457c478bd9Sstevel@tonic-gate
14467c478bd9Sstevel@tonic-gate if (spitfire_bb_fsr_bug &&
14477c478bd9Sstevel@tonic-gate (fp->fpu_fsr & FSR_TEM_NX)) {
14487c478bd9Sstevel@tonic-gate if (((fp->fpu_fsr & FSR_TEM_OF) == 0) &&
14497c478bd9Sstevel@tonic-gate (fp->fpu_fsr & FSR_CEXC_OF)) {
14507c478bd9Sstevel@tonic-gate fp->fpu_fsr &= ~FSR_CEXC_OF;
14517c478bd9Sstevel@tonic-gate fp->fpu_fsr |= FSR_CEXC_NX;
14527c478bd9Sstevel@tonic-gate _fp_write_pfsr(&fp->fpu_fsr);
14537c478bd9Sstevel@tonic-gate siginfo.si_code = FPE_FLTRES;
14547c478bd9Sstevel@tonic-gate }
14557c478bd9Sstevel@tonic-gate if (((fp->fpu_fsr & FSR_TEM_UF) == 0) &&
14567c478bd9Sstevel@tonic-gate (fp->fpu_fsr & FSR_CEXC_UF)) {
14577c478bd9Sstevel@tonic-gate fp->fpu_fsr &= ~FSR_CEXC_UF;
14587c478bd9Sstevel@tonic-gate fp->fpu_fsr |= FSR_CEXC_NX;
14597c478bd9Sstevel@tonic-gate _fp_write_pfsr(&fp->fpu_fsr);
14607c478bd9Sstevel@tonic-gate siginfo.si_code = FPE_FLTRES;
14617c478bd9Sstevel@tonic-gate }
14627c478bd9Sstevel@tonic-gate }
14637c478bd9Sstevel@tonic-gate }
14647c478bd9Sstevel@tonic-gate #endif /* SF_V9_TABLE_28 */
14657c478bd9Sstevel@tonic-gate rp->r_pc = rp->r_npc;
14667c478bd9Sstevel@tonic-gate rp->r_npc += 4;
14677c478bd9Sstevel@tonic-gate } else if (utrapp && utrapp[UT_FP_EXCEPTION_IEEE_754]) {
14687c478bd9Sstevel@tonic-gate /*
14697c478bd9Sstevel@tonic-gate * The user had a trap handler installed. Jump to
14707c478bd9Sstevel@tonic-gate * the trap handler instead of signalling the process.
14717c478bd9Sstevel@tonic-gate */
14727c478bd9Sstevel@tonic-gate rp->r_pc = (long)utrapp[UT_FP_EXCEPTION_IEEE_754];
14737c478bd9Sstevel@tonic-gate rp->r_npc = rp->r_pc + 4;
14747c478bd9Sstevel@tonic-gate break;
14757c478bd9Sstevel@tonic-gate }
14767c478bd9Sstevel@tonic-gate siginfo.si_signo = SIGFPE;
14777c478bd9Sstevel@tonic-gate fault = FLTFPE;
14787c478bd9Sstevel@tonic-gate break;
14797c478bd9Sstevel@tonic-gate
14807c478bd9Sstevel@tonic-gate case T_DATA_EXCEPTION + T_USER: /* user data access exception */
14817c478bd9Sstevel@tonic-gate siginfo.si_signo = SIGSEGV;
14827c478bd9Sstevel@tonic-gate fault = FLTBOUNDS;
14837c478bd9Sstevel@tonic-gate break;
14847c478bd9Sstevel@tonic-gate
14857c478bd9Sstevel@tonic-gate case T_LDDF_ALIGN + T_USER: /* 64 bit user lddfa alignment error */
14867c478bd9Sstevel@tonic-gate case T_STDF_ALIGN + T_USER: /* 64 bit user stdfa alignment error */
14877c478bd9Sstevel@tonic-gate alignfaults++;
14887c478bd9Sstevel@tonic-gate lwp->lwp_state = LWP_SYS;
148937e7ac7eSjfrank if (&vis1_partial_support != NULL) {
149037e7ac7eSjfrank bzero(&siginfo, sizeof (siginfo));
149137e7ac7eSjfrank if (vis1_partial_support(rp,
149237e7ac7eSjfrank &siginfo, &fault) == 0)
149337e7ac7eSjfrank goto out;
149437e7ac7eSjfrank }
14957c478bd9Sstevel@tonic-gate if (do_unaligned(rp, &badaddr) == SIMU_SUCCESS) {
14967c478bd9Sstevel@tonic-gate rp->r_pc = rp->r_npc;
14977c478bd9Sstevel@tonic-gate rp->r_npc += 4;
14987c478bd9Sstevel@tonic-gate goto out;
14997c478bd9Sstevel@tonic-gate }
15007c478bd9Sstevel@tonic-gate fp = lwptofpu(curthread->t_lwp);
15017c478bd9Sstevel@tonic-gate fp->fpu_qcnt = 0;
15027c478bd9Sstevel@tonic-gate siginfo.si_signo = SIGSEGV;
15037c478bd9Sstevel@tonic-gate siginfo.si_code = SEGV_MAPERR;
15047c478bd9Sstevel@tonic-gate siginfo.si_addr = badaddr;
15057c478bd9Sstevel@tonic-gate fault = FLTBOUNDS;
15067c478bd9Sstevel@tonic-gate break;
15077c478bd9Sstevel@tonic-gate
15087c478bd9Sstevel@tonic-gate case T_ALIGNMENT + T_USER: /* user alignment error */
15097c478bd9Sstevel@tonic-gate /*
15107c478bd9Sstevel@tonic-gate * If the user has to do unaligned references
15117c478bd9Sstevel@tonic-gate * the ugly stuff gets done here.
15127c478bd9Sstevel@tonic-gate * Only handles vanilla loads and stores.
15137c478bd9Sstevel@tonic-gate */
15147c478bd9Sstevel@tonic-gate alignfaults++;
15157c478bd9Sstevel@tonic-gate if (p->p_fixalignment) {
15167c478bd9Sstevel@tonic-gate if (do_unaligned(rp, &badaddr) == SIMU_SUCCESS) {
15177c478bd9Sstevel@tonic-gate rp->r_pc = rp->r_npc;
15187c478bd9Sstevel@tonic-gate rp->r_npc += 4;
15197c478bd9Sstevel@tonic-gate goto out;
15207c478bd9Sstevel@tonic-gate }
15217c478bd9Sstevel@tonic-gate siginfo.si_signo = SIGSEGV;
15227c478bd9Sstevel@tonic-gate siginfo.si_code = SEGV_MAPERR;
15237c478bd9Sstevel@tonic-gate siginfo.si_addr = badaddr;
15247c478bd9Sstevel@tonic-gate fault = FLTBOUNDS;
15257c478bd9Sstevel@tonic-gate } else {
15267c478bd9Sstevel@tonic-gate siginfo.si_signo = SIGBUS;
15277c478bd9Sstevel@tonic-gate siginfo.si_code = BUS_ADRALN;
15287c478bd9Sstevel@tonic-gate if (rp->r_pc & 3) { /* offending address, if pc */
15297c478bd9Sstevel@tonic-gate siginfo.si_addr = (caddr_t)rp->r_pc;
15307c478bd9Sstevel@tonic-gate } else {
15317c478bd9Sstevel@tonic-gate if (calc_memaddr(rp, &badaddr) == SIMU_UNALIGN)
15327c478bd9Sstevel@tonic-gate siginfo.si_addr = badaddr;
15337c478bd9Sstevel@tonic-gate else
15347c478bd9Sstevel@tonic-gate siginfo.si_addr = (caddr_t)rp->r_pc;
15357c478bd9Sstevel@tonic-gate }
15367c478bd9Sstevel@tonic-gate fault = FLTACCESS;
15377c478bd9Sstevel@tonic-gate }
15387c478bd9Sstevel@tonic-gate break;
15397c478bd9Sstevel@tonic-gate
15407c478bd9Sstevel@tonic-gate case T_UNIMP_INSTR + T_USER: /* illegal instruction fault */
15417c478bd9Sstevel@tonic-gate siginfo.si_signo = SIGILL;
15427c478bd9Sstevel@tonic-gate inst = fetch_user_instr((caddr_t)rp->r_pc);
15437c478bd9Sstevel@tonic-gate op3 = (inst >> 19) & 0x3F;
15447c478bd9Sstevel@tonic-gate if ((op3 == IOP_V8_STQFA) || (op3 == IOP_V8_STDFA))
15457c478bd9Sstevel@tonic-gate siginfo.si_code = ILL_ILLADR;
15467c478bd9Sstevel@tonic-gate else
15477c478bd9Sstevel@tonic-gate siginfo.si_code = ILL_ILLTRP;
15487c478bd9Sstevel@tonic-gate fault = FLTILL;
15497c478bd9Sstevel@tonic-gate break;
15507c478bd9Sstevel@tonic-gate
15517c478bd9Sstevel@tonic-gate default:
15527c478bd9Sstevel@tonic-gate (void) die(type, rp, addr, 0);
15537c478bd9Sstevel@tonic-gate /*NOTREACHED*/
15547c478bd9Sstevel@tonic-gate }
15557c478bd9Sstevel@tonic-gate
15567c478bd9Sstevel@tonic-gate /*
15577c478bd9Sstevel@tonic-gate * We can't get here from a system trap
15587c478bd9Sstevel@tonic-gate * Never restart any instruction which got here from an fp trap.
15597c478bd9Sstevel@tonic-gate */
15607c478bd9Sstevel@tonic-gate ASSERT(type & T_USER);
15617c478bd9Sstevel@tonic-gate
15627c478bd9Sstevel@tonic-gate trap_cleanup(rp, fault, &siginfo, 0);
15637c478bd9Sstevel@tonic-gate out:
15647c478bd9Sstevel@tonic-gate trap_rtt();
15657c478bd9Sstevel@tonic-gate (void) new_mstate(curthread, mstate);
15667c478bd9Sstevel@tonic-gate }
15677c478bd9Sstevel@tonic-gate
15687c478bd9Sstevel@tonic-gate void
trap_rtt(void)15697c478bd9Sstevel@tonic-gate trap_rtt(void)
15707c478bd9Sstevel@tonic-gate {
15717c478bd9Sstevel@tonic-gate klwp_id_t lwp = ttolwp(curthread);
15727c478bd9Sstevel@tonic-gate
15737c478bd9Sstevel@tonic-gate /*
15747c478bd9Sstevel@tonic-gate * Restore register window if a debugger modified it.
15757c478bd9Sstevel@tonic-gate * Set up to perform a single-step if a debugger requested it.
15767c478bd9Sstevel@tonic-gate */
15777c478bd9Sstevel@tonic-gate if (lwp->lwp_pcb.pcb_xregstat != XREGNONE)
15787c478bd9Sstevel@tonic-gate xregrestore(lwp, 0);
15797c478bd9Sstevel@tonic-gate
15807c478bd9Sstevel@tonic-gate /*
15817c478bd9Sstevel@tonic-gate * Set state to LWP_USER here so preempt won't give us a kernel
15827c478bd9Sstevel@tonic-gate * priority if it occurs after this point. Call CL_TRAPRET() to
15837c478bd9Sstevel@tonic-gate * restore the user-level priority.
15847c478bd9Sstevel@tonic-gate *
15857c478bd9Sstevel@tonic-gate * It is important that no locks (other than spinlocks) be entered
15867c478bd9Sstevel@tonic-gate * after this point before returning to user mode (unless lwp_state
15877c478bd9Sstevel@tonic-gate * is set back to LWP_SYS).
15887c478bd9Sstevel@tonic-gate */
15897c478bd9Sstevel@tonic-gate lwp->lwp_state = LWP_USER;
15907c478bd9Sstevel@tonic-gate if (curthread->t_trapret) {
15917c478bd9Sstevel@tonic-gate curthread->t_trapret = 0;
15927c478bd9Sstevel@tonic-gate thread_lock(curthread);
15937c478bd9Sstevel@tonic-gate CL_TRAPRET(curthread);
15947c478bd9Sstevel@tonic-gate thread_unlock(curthread);
15957c478bd9Sstevel@tonic-gate }
1596c97ad5cdSakolb if (CPU->cpu_runrun || curthread->t_schedflag & TS_ANYWAITQ)
15977c478bd9Sstevel@tonic-gate preempt();
159807a48826SRoger A. Faulkner prunstop();
15997c478bd9Sstevel@tonic-gate if (lwp->lwp_pcb.pcb_step != STEP_NONE)
16007c478bd9Sstevel@tonic-gate prdostep();
16017c478bd9Sstevel@tonic-gate
16027c478bd9Sstevel@tonic-gate TRACE_0(TR_FAC_TRAP, TR_C_TRAP_HANDLER_EXIT, "C_trap_handler_exit");
16037c478bd9Sstevel@tonic-gate }
16047c478bd9Sstevel@tonic-gate
16057c478bd9Sstevel@tonic-gate #define IS_LDASI(o) \
16067c478bd9Sstevel@tonic-gate ((o) == (uint32_t)0xC0C00000 || (o) == (uint32_t)0xC0800000 || \
16077c478bd9Sstevel@tonic-gate (o) == (uint32_t)0xC1800000)
16087c478bd9Sstevel@tonic-gate #define IS_IMM_ASI(i) (((i) & 0x2000) == 0)
16097c478bd9Sstevel@tonic-gate #define IS_ASINF(a) (((a) & 0xF6) == 0x82)
16107c478bd9Sstevel@tonic-gate #define IS_LDDA(i) (((i) & 0xC1F80000) == 0xC0980000)
16117c478bd9Sstevel@tonic-gate
16127c478bd9Sstevel@tonic-gate static int
nfload(struct regs * rp,int * instrp)16137c478bd9Sstevel@tonic-gate nfload(struct regs *rp, int *instrp)
16147c478bd9Sstevel@tonic-gate {
16157c478bd9Sstevel@tonic-gate uint_t instr, asi, op3, rd;
16167c478bd9Sstevel@tonic-gate size_t len;
16177c478bd9Sstevel@tonic-gate struct as *as;
16187c478bd9Sstevel@tonic-gate caddr_t addr;
16197c478bd9Sstevel@tonic-gate FPU_DREGS_TYPE zero;
16207c478bd9Sstevel@tonic-gate extern int segnf_create();
16217c478bd9Sstevel@tonic-gate
16227c478bd9Sstevel@tonic-gate if (USERMODE(rp->r_tstate))
16237c478bd9Sstevel@tonic-gate instr = fetch_user_instr((caddr_t)rp->r_pc);
16247c478bd9Sstevel@tonic-gate else
16257c478bd9Sstevel@tonic-gate instr = *(int *)rp->r_pc;
16267c478bd9Sstevel@tonic-gate
16277c478bd9Sstevel@tonic-gate if (instrp)
16287c478bd9Sstevel@tonic-gate *instrp = instr;
16297c478bd9Sstevel@tonic-gate
16307c478bd9Sstevel@tonic-gate op3 = (uint_t)(instr & 0xC1E00000);
16317c478bd9Sstevel@tonic-gate if (!IS_LDASI(op3))
16327c478bd9Sstevel@tonic-gate return (0);
16337c478bd9Sstevel@tonic-gate if (IS_IMM_ASI(instr))
16347c478bd9Sstevel@tonic-gate asi = (instr & 0x1FE0) >> 5;
16357c478bd9Sstevel@tonic-gate else
16367c478bd9Sstevel@tonic-gate asi = (uint_t)((rp->r_tstate >> TSTATE_ASI_SHIFT) &
16377c478bd9Sstevel@tonic-gate TSTATE_ASI_MASK);
16387c478bd9Sstevel@tonic-gate if (!IS_ASINF(asi))
16397c478bd9Sstevel@tonic-gate return (0);
16407c478bd9Sstevel@tonic-gate if (calc_memaddr(rp, &addr) == SIMU_SUCCESS) {
16417c478bd9Sstevel@tonic-gate len = 1;
16427c478bd9Sstevel@tonic-gate as = USERMODE(rp->r_tstate) ? ttoproc(curthread)->p_as : &kas;
16437c478bd9Sstevel@tonic-gate as_rangelock(as);
16447c478bd9Sstevel@tonic-gate if (as_gap(as, len, &addr, &len, 0, addr) == 0)
16457c478bd9Sstevel@tonic-gate (void) as_map(as, addr, len, segnf_create, NULL);
16467c478bd9Sstevel@tonic-gate as_rangeunlock(as);
16477c478bd9Sstevel@tonic-gate }
16487c478bd9Sstevel@tonic-gate zero = 0;
16497c478bd9Sstevel@tonic-gate rd = (instr >> 25) & 0x1f;
16507c478bd9Sstevel@tonic-gate if (IS_FLOAT(instr)) {
16517c478bd9Sstevel@tonic-gate uint_t dbflg = ((instr >> 19) & 3) == 3;
16527c478bd9Sstevel@tonic-gate
16537c478bd9Sstevel@tonic-gate if (dbflg) { /* clever v9 reg encoding */
16547c478bd9Sstevel@tonic-gate if (rd & 1)
16557c478bd9Sstevel@tonic-gate rd = (rd & 0x1e) | 0x20;
16567c478bd9Sstevel@tonic-gate rd >>= 1;
16577c478bd9Sstevel@tonic-gate }
16587c478bd9Sstevel@tonic-gate if (fpu_exists) {
16597c478bd9Sstevel@tonic-gate if (!(_fp_read_fprs() & FPRS_FEF))
16607c478bd9Sstevel@tonic-gate fp_enable();
16617c478bd9Sstevel@tonic-gate
16627c478bd9Sstevel@tonic-gate if (dbflg)
16637c478bd9Sstevel@tonic-gate _fp_write_pdreg(&zero, rd);
16647c478bd9Sstevel@tonic-gate else
16657c478bd9Sstevel@tonic-gate _fp_write_pfreg((uint_t *)&zero, rd);
16667c478bd9Sstevel@tonic-gate } else {
16677c478bd9Sstevel@tonic-gate kfpu_t *fp = lwptofpu(curthread->t_lwp);
16687c478bd9Sstevel@tonic-gate
16697c478bd9Sstevel@tonic-gate if (!fp->fpu_en)
16707c478bd9Sstevel@tonic-gate fp_enable();
16717c478bd9Sstevel@tonic-gate
16727c478bd9Sstevel@tonic-gate if (dbflg)
16737c478bd9Sstevel@tonic-gate fp->fpu_fr.fpu_dregs[rd] = zero;
16747c478bd9Sstevel@tonic-gate else
16757c478bd9Sstevel@tonic-gate fp->fpu_fr.fpu_regs[rd] = 0;
16767c478bd9Sstevel@tonic-gate }
16777c478bd9Sstevel@tonic-gate } else {
16787c478bd9Sstevel@tonic-gate (void) putreg(&zero, rp, rd, &addr);
16797c478bd9Sstevel@tonic-gate if (IS_LDDA(instr))
16807c478bd9Sstevel@tonic-gate (void) putreg(&zero, rp, rd + 1, &addr);
16817c478bd9Sstevel@tonic-gate }
16827c478bd9Sstevel@tonic-gate rp->r_pc = rp->r_npc;
16837c478bd9Sstevel@tonic-gate rp->r_npc += 4;
16847c478bd9Sstevel@tonic-gate return (1);
16857c478bd9Sstevel@tonic-gate }
16867c478bd9Sstevel@tonic-gate
16877c478bd9Sstevel@tonic-gate kmutex_t atomic_nc_mutex;
16887c478bd9Sstevel@tonic-gate
16897c478bd9Sstevel@tonic-gate /*
16907c478bd9Sstevel@tonic-gate * The following couple of routines are for userland drivers which
16917c478bd9Sstevel@tonic-gate * do atomics to noncached addresses. This sort of worked on previous
16927c478bd9Sstevel@tonic-gate * platforms -- the operation really wasn't atomic, but it didn't generate
16937c478bd9Sstevel@tonic-gate * a trap as sun4u systems do.
16947c478bd9Sstevel@tonic-gate */
16957c478bd9Sstevel@tonic-gate static int
swap_nc(struct regs * rp,int instr)16967c478bd9Sstevel@tonic-gate swap_nc(struct regs *rp, int instr)
16977c478bd9Sstevel@tonic-gate {
16987c478bd9Sstevel@tonic-gate uint64_t rdata, mdata;
16997c478bd9Sstevel@tonic-gate caddr_t addr, badaddr;
17007c478bd9Sstevel@tonic-gate uint_t tmp, rd;
17017c478bd9Sstevel@tonic-gate
17027c478bd9Sstevel@tonic-gate (void) flush_user_windows_to_stack(NULL);
17037c478bd9Sstevel@tonic-gate rd = (instr >> 25) & 0x1f;
17047c478bd9Sstevel@tonic-gate if (calc_memaddr(rp, &addr) != SIMU_SUCCESS)
17057c478bd9Sstevel@tonic-gate return (0);
17067c478bd9Sstevel@tonic-gate if (getreg(rp, rd, &rdata, &badaddr))
17077c478bd9Sstevel@tonic-gate return (0);
17087c478bd9Sstevel@tonic-gate mutex_enter(&atomic_nc_mutex);
17097c478bd9Sstevel@tonic-gate if (fuword32(addr, &tmp) == -1) {
17107c478bd9Sstevel@tonic-gate mutex_exit(&atomic_nc_mutex);
17117c478bd9Sstevel@tonic-gate return (0);
17127c478bd9Sstevel@tonic-gate }
17137c478bd9Sstevel@tonic-gate mdata = (u_longlong_t)tmp;
17147c478bd9Sstevel@tonic-gate if (suword32(addr, (uint32_t)rdata) == -1) {
17157c478bd9Sstevel@tonic-gate mutex_exit(&atomic_nc_mutex);
17167c478bd9Sstevel@tonic-gate return (0);
17177c478bd9Sstevel@tonic-gate }
17187c478bd9Sstevel@tonic-gate (void) putreg(&mdata, rp, rd, &badaddr);
17197c478bd9Sstevel@tonic-gate mutex_exit(&atomic_nc_mutex);
17207c478bd9Sstevel@tonic-gate return (1);
17217c478bd9Sstevel@tonic-gate }
17227c478bd9Sstevel@tonic-gate
17237c478bd9Sstevel@tonic-gate static int
ldstub_nc(struct regs * rp,int instr)17247c478bd9Sstevel@tonic-gate ldstub_nc(struct regs *rp, int instr)
17257c478bd9Sstevel@tonic-gate {
17267c478bd9Sstevel@tonic-gate uint64_t mdata;
17277c478bd9Sstevel@tonic-gate caddr_t addr, badaddr;
17287c478bd9Sstevel@tonic-gate uint_t rd;
17297c478bd9Sstevel@tonic-gate uint8_t tmp;
17307c478bd9Sstevel@tonic-gate
17317c478bd9Sstevel@tonic-gate (void) flush_user_windows_to_stack(NULL);
17327c478bd9Sstevel@tonic-gate rd = (instr >> 25) & 0x1f;
17337c478bd9Sstevel@tonic-gate if (calc_memaddr(rp, &addr) != SIMU_SUCCESS)
17347c478bd9Sstevel@tonic-gate return (0);
17357c478bd9Sstevel@tonic-gate mutex_enter(&atomic_nc_mutex);
17367c478bd9Sstevel@tonic-gate if (fuword8(addr, &tmp) == -1) {
17377c478bd9Sstevel@tonic-gate mutex_exit(&atomic_nc_mutex);
17387c478bd9Sstevel@tonic-gate return (0);
17397c478bd9Sstevel@tonic-gate }
17407c478bd9Sstevel@tonic-gate mdata = (u_longlong_t)tmp;
17417c478bd9Sstevel@tonic-gate if (suword8(addr, (uint8_t)0xff) == -1) {
17427c478bd9Sstevel@tonic-gate mutex_exit(&atomic_nc_mutex);
17437c478bd9Sstevel@tonic-gate return (0);
17447c478bd9Sstevel@tonic-gate }
17457c478bd9Sstevel@tonic-gate (void) putreg(&mdata, rp, rd, &badaddr);
17467c478bd9Sstevel@tonic-gate mutex_exit(&atomic_nc_mutex);
17477c478bd9Sstevel@tonic-gate return (1);
17487c478bd9Sstevel@tonic-gate }
17497c478bd9Sstevel@tonic-gate
17507c478bd9Sstevel@tonic-gate /*
17517c478bd9Sstevel@tonic-gate * This function helps instr_size() determine the operand size.
17527c478bd9Sstevel@tonic-gate * It is called for the extended ldda/stda asi's.
17537c478bd9Sstevel@tonic-gate */
17547c478bd9Sstevel@tonic-gate int
extended_asi_size(int asi)17557c478bd9Sstevel@tonic-gate extended_asi_size(int asi)
17567c478bd9Sstevel@tonic-gate {
17577c478bd9Sstevel@tonic-gate switch (asi) {
17587c478bd9Sstevel@tonic-gate case ASI_PST8_P:
17597c478bd9Sstevel@tonic-gate case ASI_PST8_S:
17607c478bd9Sstevel@tonic-gate case ASI_PST16_P:
17617c478bd9Sstevel@tonic-gate case ASI_PST16_S:
17627c478bd9Sstevel@tonic-gate case ASI_PST32_P:
17637c478bd9Sstevel@tonic-gate case ASI_PST32_S:
17647c478bd9Sstevel@tonic-gate case ASI_PST8_PL:
17657c478bd9Sstevel@tonic-gate case ASI_PST8_SL:
17667c478bd9Sstevel@tonic-gate case ASI_PST16_PL:
17677c478bd9Sstevel@tonic-gate case ASI_PST16_SL:
17687c478bd9Sstevel@tonic-gate case ASI_PST32_PL:
17697c478bd9Sstevel@tonic-gate case ASI_PST32_SL:
17707c478bd9Sstevel@tonic-gate return (8);
17717c478bd9Sstevel@tonic-gate case ASI_FL8_P:
17727c478bd9Sstevel@tonic-gate case ASI_FL8_S:
17737c478bd9Sstevel@tonic-gate case ASI_FL8_PL:
17747c478bd9Sstevel@tonic-gate case ASI_FL8_SL:
17757c478bd9Sstevel@tonic-gate return (1);
17767c478bd9Sstevel@tonic-gate case ASI_FL16_P:
17777c478bd9Sstevel@tonic-gate case ASI_FL16_S:
17787c478bd9Sstevel@tonic-gate case ASI_FL16_PL:
17797c478bd9Sstevel@tonic-gate case ASI_FL16_SL:
17807c478bd9Sstevel@tonic-gate return (2);
17817c478bd9Sstevel@tonic-gate case ASI_BLK_P:
17827c478bd9Sstevel@tonic-gate case ASI_BLK_S:
17837c478bd9Sstevel@tonic-gate case ASI_BLK_PL:
17847c478bd9Sstevel@tonic-gate case ASI_BLK_SL:
17857c478bd9Sstevel@tonic-gate case ASI_BLK_COMMIT_P:
17867c478bd9Sstevel@tonic-gate case ASI_BLK_COMMIT_S:
17877c478bd9Sstevel@tonic-gate return (64);
17887c478bd9Sstevel@tonic-gate }
17897c478bd9Sstevel@tonic-gate
17907c478bd9Sstevel@tonic-gate return (0);
17917c478bd9Sstevel@tonic-gate }
17927c478bd9Sstevel@tonic-gate
17937c478bd9Sstevel@tonic-gate /*
17947c478bd9Sstevel@tonic-gate * Patch non-zero to disable preemption of threads in the kernel.
17957c478bd9Sstevel@tonic-gate */
17967c478bd9Sstevel@tonic-gate int IGNORE_KERNEL_PREEMPTION = 0; /* XXX - delete this someday */
17977c478bd9Sstevel@tonic-gate
17987c478bd9Sstevel@tonic-gate struct kpreempt_cnts { /* kernel preemption statistics */
17997c478bd9Sstevel@tonic-gate int kpc_idle; /* executing idle thread */
18007c478bd9Sstevel@tonic-gate int kpc_intr; /* executing interrupt thread */
18017c478bd9Sstevel@tonic-gate int kpc_clock; /* executing clock thread */
18027c478bd9Sstevel@tonic-gate int kpc_blocked; /* thread has blocked preemption (t_preempt) */
18037c478bd9Sstevel@tonic-gate int kpc_notonproc; /* thread is surrendering processor */
18047c478bd9Sstevel@tonic-gate int kpc_inswtch; /* thread has ratified scheduling decision */
18057c478bd9Sstevel@tonic-gate int kpc_prilevel; /* processor interrupt level is too high */
18067c478bd9Sstevel@tonic-gate int kpc_apreempt; /* asynchronous preemption */
18077c478bd9Sstevel@tonic-gate int kpc_spreempt; /* synchronous preemption */
18087c478bd9Sstevel@tonic-gate } kpreempt_cnts;
18097c478bd9Sstevel@tonic-gate
18107c478bd9Sstevel@tonic-gate /*
18117c478bd9Sstevel@tonic-gate * kernel preemption: forced rescheduling
18127c478bd9Sstevel@tonic-gate * preempt the running kernel thread.
18137c478bd9Sstevel@tonic-gate */
18147c478bd9Sstevel@tonic-gate void
kpreempt(int asyncspl)18157c478bd9Sstevel@tonic-gate kpreempt(int asyncspl)
18167c478bd9Sstevel@tonic-gate {
18177c478bd9Sstevel@tonic-gate if (IGNORE_KERNEL_PREEMPTION) {
18187c478bd9Sstevel@tonic-gate aston(CPU->cpu_dispthread);
18197c478bd9Sstevel@tonic-gate return;
18207c478bd9Sstevel@tonic-gate }
18217c478bd9Sstevel@tonic-gate /*
18227c478bd9Sstevel@tonic-gate * Check that conditions are right for kernel preemption
18237c478bd9Sstevel@tonic-gate */
18247c478bd9Sstevel@tonic-gate do {
18257c478bd9Sstevel@tonic-gate if (curthread->t_preempt) {
18267c478bd9Sstevel@tonic-gate /*
18277c478bd9Sstevel@tonic-gate * either a privileged thread (idle, panic, interrupt)
18287c478bd9Sstevel@tonic-gate * or will check when t_preempt is lowered
1829b6d5e9b6SPramod Batni * We need to specifically handle the case where
1830b6d5e9b6SPramod Batni * the thread is in the middle of swtch (resume has
1831b6d5e9b6SPramod Batni * been called) and has its t_preempt set
1832b6d5e9b6SPramod Batni * [idle thread and a thread which is in kpreempt
1833b6d5e9b6SPramod Batni * already] and then a high priority thread is
1834b6d5e9b6SPramod Batni * available in the local dispatch queue.
1835b6d5e9b6SPramod Batni * In this case the resumed thread needs to take a
1836b6d5e9b6SPramod Batni * trap so that it can call kpreempt. We achieve
1837b6d5e9b6SPramod Batni * this by using siron().
1838b6d5e9b6SPramod Batni * How do we detect this condition:
1839b6d5e9b6SPramod Batni * idle thread is running and is in the midst of
1840b6d5e9b6SPramod Batni * resume: curthread->t_pri == -1 && CPU->dispthread
1841b6d5e9b6SPramod Batni * != CPU->thread
1842b6d5e9b6SPramod Batni * Need to ensure that this happens only at high pil
1843b6d5e9b6SPramod Batni * resume is called at high pil
1844b6d5e9b6SPramod Batni * Only in resume_from_idle is the pil changed.
18457c478bd9Sstevel@tonic-gate */
1846b6d5e9b6SPramod Batni if (curthread->t_pri < 0) {
18477c478bd9Sstevel@tonic-gate kpreempt_cnts.kpc_idle++;
1848b6d5e9b6SPramod Batni if (CPU->cpu_dispthread != CPU->cpu_thread)
1849b6d5e9b6SPramod Batni siron();
1850b6d5e9b6SPramod Batni } else if (curthread->t_flag & T_INTR_THREAD) {
18517c478bd9Sstevel@tonic-gate kpreempt_cnts.kpc_intr++;
18527c478bd9Sstevel@tonic-gate if (curthread->t_pil == CLOCK_LEVEL)
18537c478bd9Sstevel@tonic-gate kpreempt_cnts.kpc_clock++;
1854b6d5e9b6SPramod Batni } else {
18557c478bd9Sstevel@tonic-gate kpreempt_cnts.kpc_blocked++;
1856b6d5e9b6SPramod Batni if (CPU->cpu_dispthread != CPU->cpu_thread)
1857b6d5e9b6SPramod Batni siron();
1858b6d5e9b6SPramod Batni }
18597c478bd9Sstevel@tonic-gate aston(CPU->cpu_dispthread);
18607c478bd9Sstevel@tonic-gate return;
18617c478bd9Sstevel@tonic-gate }
18627c478bd9Sstevel@tonic-gate if (curthread->t_state != TS_ONPROC ||
18637c478bd9Sstevel@tonic-gate curthread->t_disp_queue != CPU->cpu_disp) {
18647c478bd9Sstevel@tonic-gate /* this thread will be calling swtch() shortly */
18657c478bd9Sstevel@tonic-gate kpreempt_cnts.kpc_notonproc++;
18667c478bd9Sstevel@tonic-gate if (CPU->cpu_thread != CPU->cpu_dispthread) {
18677c478bd9Sstevel@tonic-gate /* already in swtch(), force another */
18687c478bd9Sstevel@tonic-gate kpreempt_cnts.kpc_inswtch++;
18697c478bd9Sstevel@tonic-gate siron();
18707c478bd9Sstevel@tonic-gate }
18717c478bd9Sstevel@tonic-gate return;
18727c478bd9Sstevel@tonic-gate }
18737c478bd9Sstevel@tonic-gate
18747c478bd9Sstevel@tonic-gate if (((asyncspl != KPREEMPT_SYNC) ? spltoipl(asyncspl) :
18757c478bd9Sstevel@tonic-gate getpil()) >= DISP_LEVEL) {
18767c478bd9Sstevel@tonic-gate /*
18777c478bd9Sstevel@tonic-gate * We can't preempt this thread if it is at
18787c478bd9Sstevel@tonic-gate * a PIL >= DISP_LEVEL since it may be holding
18797c478bd9Sstevel@tonic-gate * a spin lock (like sched_lock).
18807c478bd9Sstevel@tonic-gate */
18817c478bd9Sstevel@tonic-gate siron(); /* check back later */
18827c478bd9Sstevel@tonic-gate kpreempt_cnts.kpc_prilevel++;
18837c478bd9Sstevel@tonic-gate return;
18847c478bd9Sstevel@tonic-gate }
18857c478bd9Sstevel@tonic-gate
18867c478bd9Sstevel@tonic-gate /*
18877c478bd9Sstevel@tonic-gate * block preemption so we don't have multiple preemptions
18887c478bd9Sstevel@tonic-gate * pending on the interrupt stack
18897c478bd9Sstevel@tonic-gate */
18907c478bd9Sstevel@tonic-gate curthread->t_preempt++;
18917c478bd9Sstevel@tonic-gate if (asyncspl != KPREEMPT_SYNC) {
18927c478bd9Sstevel@tonic-gate splx(asyncspl);
18937c478bd9Sstevel@tonic-gate kpreempt_cnts.kpc_apreempt++;
18947c478bd9Sstevel@tonic-gate } else
18957c478bd9Sstevel@tonic-gate kpreempt_cnts.kpc_spreempt++;
18967c478bd9Sstevel@tonic-gate
18977c478bd9Sstevel@tonic-gate preempt();
18987c478bd9Sstevel@tonic-gate curthread->t_preempt--;
18997c478bd9Sstevel@tonic-gate } while (CPU->cpu_kprunrun);
19007c478bd9Sstevel@tonic-gate }
19017c478bd9Sstevel@tonic-gate
19027c478bd9Sstevel@tonic-gate static enum seg_rw
get_accesstype(struct regs * rp)19037c478bd9Sstevel@tonic-gate get_accesstype(struct regs *rp)
19047c478bd9Sstevel@tonic-gate {
19057c478bd9Sstevel@tonic-gate uint32_t instr;
19067c478bd9Sstevel@tonic-gate
19077c478bd9Sstevel@tonic-gate if (USERMODE(rp->r_tstate))
19087c478bd9Sstevel@tonic-gate instr = fetch_user_instr((caddr_t)rp->r_pc);
19097c478bd9Sstevel@tonic-gate else
19107c478bd9Sstevel@tonic-gate instr = *(uint32_t *)rp->r_pc;
19117c478bd9Sstevel@tonic-gate
19127c478bd9Sstevel@tonic-gate if (IS_FLUSH(instr))
19137c478bd9Sstevel@tonic-gate return (S_OTHER);
19147c478bd9Sstevel@tonic-gate
19157c478bd9Sstevel@tonic-gate if (IS_STORE(instr))
19167c478bd9Sstevel@tonic-gate return (S_WRITE);
19177c478bd9Sstevel@tonic-gate else
19187c478bd9Sstevel@tonic-gate return (S_READ);
19197c478bd9Sstevel@tonic-gate }
1920d6c90996SAbhinandan Ekande
1921d6c90996SAbhinandan Ekande /*
1922d6c90996SAbhinandan Ekande * Handle an asynchronous hardware error.
1923d6c90996SAbhinandan Ekande * The policy is currently to send a hardware error contract event to
1924d6c90996SAbhinandan Ekande * the process's process contract and to kill the process. Eventually
1925d6c90996SAbhinandan Ekande * we may want to instead send a special signal whose default
1926d6c90996SAbhinandan Ekande * disposition is to generate the contract event.
1927d6c90996SAbhinandan Ekande */
1928d6c90996SAbhinandan Ekande void
trap_async_hwerr(void)1929d6c90996SAbhinandan Ekande trap_async_hwerr(void)
1930d6c90996SAbhinandan Ekande {
1931d6c90996SAbhinandan Ekande k_siginfo_t si;
1932d6c90996SAbhinandan Ekande proc_t *p = ttoproc(curthread);
1933d6c90996SAbhinandan Ekande extern void print_msg_hwerr(ctid_t ct_id, proc_t *p);
1934d6c90996SAbhinandan Ekande
1935d6c90996SAbhinandan Ekande errorq_drain(ue_queue); /* flush pending async error messages */
1936d6c90996SAbhinandan Ekande
1937d6c90996SAbhinandan Ekande print_msg_hwerr(p->p_ct_process->conp_contract.ct_id, p);
1938d6c90996SAbhinandan Ekande
1939d6c90996SAbhinandan Ekande contract_process_hwerr(p->p_ct_process, p);
1940d6c90996SAbhinandan Ekande
1941d6c90996SAbhinandan Ekande bzero(&si, sizeof (k_siginfo_t));
1942d6c90996SAbhinandan Ekande si.si_signo = SIGKILL;
1943d6c90996SAbhinandan Ekande si.si_code = SI_NOINFO;
1944d6c90996SAbhinandan Ekande trapsig(&si, 1);
1945d6c90996SAbhinandan Ekande }
1946d6c90996SAbhinandan Ekande
1947d6c90996SAbhinandan Ekande /*
1948d6c90996SAbhinandan Ekande * Handle bus error and bus timeout for a user process by sending SIGBUS
1949d6c90996SAbhinandan Ekande * The type is either ASYNC_BERR or ASYNC_BTO.
1950d6c90996SAbhinandan Ekande */
1951d6c90996SAbhinandan Ekande void
trap_async_berr_bto(int type,struct regs * rp)1952d6c90996SAbhinandan Ekande trap_async_berr_bto(int type, struct regs *rp)
1953d6c90996SAbhinandan Ekande {
1954d6c90996SAbhinandan Ekande k_siginfo_t si;
1955d6c90996SAbhinandan Ekande
1956d6c90996SAbhinandan Ekande errorq_drain(ue_queue); /* flush pending async error messages */
1957d6c90996SAbhinandan Ekande bzero(&si, sizeof (k_siginfo_t));
1958d6c90996SAbhinandan Ekande
1959d6c90996SAbhinandan Ekande si.si_signo = SIGBUS;
1960d6c90996SAbhinandan Ekande si.si_code = (type == ASYNC_BERR ? BUS_OBJERR : BUS_ADRERR);
1961d6c90996SAbhinandan Ekande si.si_addr = (caddr_t)rp->r_pc; /* AFAR unavailable - future RFE */
1962d6c90996SAbhinandan Ekande si.si_errno = ENXIO;
1963d6c90996SAbhinandan Ekande
1964d6c90996SAbhinandan Ekande trapsig(&si, 1);
1965d6c90996SAbhinandan Ekande }
1966