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 58efd794bSsudheer * Common Development and Distribution License (the "License"). 68efd794bSsudheer * 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 */ 21c4978b50Sraf 227c478bd9Sstevel@tonic-gate /* 2396992ee7SEthindra Ramamurthy * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. 24*2c164fafSPatrick Mooney * Copyright 2019 Joyent, Inc. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #include <sys/param.h> 287c478bd9Sstevel@tonic-gate #include <sys/vmparam.h> 297c478bd9Sstevel@tonic-gate #include <sys/types.h> 307c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 317c478bd9Sstevel@tonic-gate #include <sys/systm.h> 327c478bd9Sstevel@tonic-gate #include <sys/signal.h> 337c478bd9Sstevel@tonic-gate #include <sys/stack.h> 347c478bd9Sstevel@tonic-gate #include <sys/cred.h> 357c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 367c478bd9Sstevel@tonic-gate #include <sys/user.h> 377c478bd9Sstevel@tonic-gate #include <sys/privregs.h> 387c478bd9Sstevel@tonic-gate #include <sys/psw.h> 397c478bd9Sstevel@tonic-gate #include <sys/debug.h> 407c478bd9Sstevel@tonic-gate #include <sys/errno.h> 417c478bd9Sstevel@tonic-gate #include <sys/proc.h> 427c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 437c478bd9Sstevel@tonic-gate #include <sys/var.h> 447c478bd9Sstevel@tonic-gate #include <sys/inline.h> 457c478bd9Sstevel@tonic-gate #include <sys/syscall.h> 467c478bd9Sstevel@tonic-gate #include <sys/ucontext.h> 477c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h> 487c478bd9Sstevel@tonic-gate #include <sys/siginfo.h> 497c478bd9Sstevel@tonic-gate #include <sys/trap.h> 507c478bd9Sstevel@tonic-gate #include <sys/vtrace.h> 517c478bd9Sstevel@tonic-gate #include <sys/sysinfo.h> 527c478bd9Sstevel@tonic-gate #include <sys/procfs.h> 5307a48826SRoger A. Faulkner #include <sys/prsystm.h> 547c478bd9Sstevel@tonic-gate #include <c2/audit.h> 557c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 567c478bd9Sstevel@tonic-gate #include <sys/aio_impl.h> 577c478bd9Sstevel@tonic-gate #include <sys/tnf.h> 587c478bd9Sstevel@tonic-gate #include <sys/tnf_probe.h> 597c478bd9Sstevel@tonic-gate #include <sys/copyops.h> 607c478bd9Sstevel@tonic-gate #include <sys/priv.h> 617c478bd9Sstevel@tonic-gate #include <sys/msacct.h> 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate int syscalltrace = 0; 647c478bd9Sstevel@tonic-gate #ifdef SYSCALLTRACE 657c478bd9Sstevel@tonic-gate static kmutex_t systrace_lock; /* syscall tracing lock */ 667c478bd9Sstevel@tonic-gate #else 677c478bd9Sstevel@tonic-gate #define syscalltrace 0 687c478bd9Sstevel@tonic-gate #endif /* SYSCALLTRACE */ 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate typedef int64_t (*llfcn_t)(); /* function returning long long */ 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate int pre_syscall(void); 737c478bd9Sstevel@tonic-gate void post_syscall(long rval1, long rval2); 747c478bd9Sstevel@tonic-gate static krwlock_t *lock_syscall(struct sysent *, uint_t); 75d8aa0f5aSsudheer void deferred_singlestep_trap(caddr_t); 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 787c478bd9Sstevel@tonic-gate #define LWP_GETSYSENT(lwp) \ 797c478bd9Sstevel@tonic-gate (lwp_getdatamodel(lwp) == DATAMODEL_NATIVE ? sysent : sysent32) 807c478bd9Sstevel@tonic-gate #else 817c478bd9Sstevel@tonic-gate #define LWP_GETSYSENT(lwp) (sysent) 827c478bd9Sstevel@tonic-gate #endif 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate /* 857c478bd9Sstevel@tonic-gate * If watchpoints are active, don't make copying in of 867c478bd9Sstevel@tonic-gate * system call arguments take a read watchpoint trap. 877c478bd9Sstevel@tonic-gate */ 887c478bd9Sstevel@tonic-gate static int 897c478bd9Sstevel@tonic-gate copyin_args(struct regs *rp, long *ap, uint_t nargs) 907c478bd9Sstevel@tonic-gate { 917c478bd9Sstevel@tonic-gate greg_t *sp = 1 + (greg_t *)rp->r_sp; /* skip ret addr */ 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate ASSERT(nargs <= MAXSYSARGS); 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate return (copyin_nowatch(sp, ap, nargs * sizeof (*sp))); 967c478bd9Sstevel@tonic-gate } 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate #if defined(_SYSCALL32_IMPL) 997c478bd9Sstevel@tonic-gate static int 1007c478bd9Sstevel@tonic-gate copyin_args32(struct regs *rp, long *ap, uint_t nargs) 1017c478bd9Sstevel@tonic-gate { 1027c478bd9Sstevel@tonic-gate greg32_t *sp = 1 + (greg32_t *)rp->r_sp; /* skip ret addr */ 1037c478bd9Sstevel@tonic-gate uint32_t a32[MAXSYSARGS]; 1047c478bd9Sstevel@tonic-gate int rc; 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate ASSERT(nargs <= MAXSYSARGS); 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate if ((rc = copyin_nowatch(sp, a32, nargs * sizeof (*sp))) == 0) { 1097c478bd9Sstevel@tonic-gate uint32_t *a32p = &a32[0]; 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate while (nargs--) 1127c478bd9Sstevel@tonic-gate *ap++ = (ulong_t)*a32p++; 1137c478bd9Sstevel@tonic-gate } 1147c478bd9Sstevel@tonic-gate return (rc); 1157c478bd9Sstevel@tonic-gate } 1167c478bd9Sstevel@tonic-gate #define COPYIN_ARGS32 copyin_args32 1177c478bd9Sstevel@tonic-gate #else 1187c478bd9Sstevel@tonic-gate #define COPYIN_ARGS32 copyin_args 1197c478bd9Sstevel@tonic-gate #endif 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate /* 1227c478bd9Sstevel@tonic-gate * Error handler for system calls where arg copy gets fault. 1237c478bd9Sstevel@tonic-gate */ 1247c478bd9Sstevel@tonic-gate static longlong_t 1257c478bd9Sstevel@tonic-gate syscall_err() 1267c478bd9Sstevel@tonic-gate { 1277c478bd9Sstevel@tonic-gate return (0); 1287c478bd9Sstevel@tonic-gate } 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate /* 1317c478bd9Sstevel@tonic-gate * Corresponding sysent entry to allow syscall_entry caller 1327c478bd9Sstevel@tonic-gate * to invoke syscall_err. 1337c478bd9Sstevel@tonic-gate */ 1347c478bd9Sstevel@tonic-gate static struct sysent sysent_err = { 1357c478bd9Sstevel@tonic-gate 0, SE_32RVAL1, NULL, NULL, (llfcn_t)syscall_err 1367c478bd9Sstevel@tonic-gate }; 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate /* 1397c478bd9Sstevel@tonic-gate * Called from syscall() when a non-trivial 32-bit system call occurs. 1407c478bd9Sstevel@tonic-gate * Sets up the args and returns a pointer to the handler. 1417c478bd9Sstevel@tonic-gate */ 1427c478bd9Sstevel@tonic-gate struct sysent * 1437c478bd9Sstevel@tonic-gate syscall_entry(kthread_t *t, long *argp) 1447c478bd9Sstevel@tonic-gate { 1457c478bd9Sstevel@tonic-gate klwp_t *lwp = ttolwp(t); 1467c478bd9Sstevel@tonic-gate struct regs *rp = lwptoregs(lwp); 1477c478bd9Sstevel@tonic-gate unsigned int code; 1487c478bd9Sstevel@tonic-gate struct sysent *callp; 1497c478bd9Sstevel@tonic-gate struct sysent *se = LWP_GETSYSENT(lwp); 1507c478bd9Sstevel@tonic-gate int error = 0; 1517c478bd9Sstevel@tonic-gate uint_t nargs; 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate ASSERT(t == curthread && curthread->t_schedflag & TS_DONT_SWAP); 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate lwp->lwp_ru.sysc++; 1567c478bd9Sstevel@tonic-gate lwp->lwp_eosys = NORMALRETURN; /* assume this will be normal */ 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate /* 1597c478bd9Sstevel@tonic-gate * Set lwp_ap to point to the args, even if none are needed for this 1607c478bd9Sstevel@tonic-gate * system call. This is for the loadable-syscall case where the 1617c478bd9Sstevel@tonic-gate * number of args won't be known until the system call is loaded, and 1627c478bd9Sstevel@tonic-gate * also maintains a non-NULL lwp_ap setup for get_syscall_args(). Note 1637c478bd9Sstevel@tonic-gate * that lwp_ap MUST be set to a non-NULL value _BEFORE_ t_sysnum is 1647c478bd9Sstevel@tonic-gate * set to non-zero; otherwise get_syscall_args(), seeing a non-zero 1657c478bd9Sstevel@tonic-gate * t_sysnum for this thread, will charge ahead and dereference lwp_ap. 1667c478bd9Sstevel@tonic-gate */ 1677c478bd9Sstevel@tonic-gate lwp->lwp_ap = argp; /* for get_syscall_args */ 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate code = rp->r_r0; 1707c478bd9Sstevel@tonic-gate t->t_sysnum = (short)code; 1717c478bd9Sstevel@tonic-gate callp = code >= NSYSCALL ? &nosys_ent : se + code; 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate if ((t->t_pre_sys | syscalltrace) != 0) { 1747c478bd9Sstevel@tonic-gate error = pre_syscall(); 175be0c6780Sdmick 1767c478bd9Sstevel@tonic-gate /* 177be0c6780Sdmick * pre_syscall() has taken care so that lwp_ap is current; 178be0c6780Sdmick * it either points to syscall-entry-saved amd64 regs, 179be0c6780Sdmick * or it points to lwp_arg[], which has been re-copied from 180be0c6780Sdmick * the ia32 ustack, but either way, it's a current copy after 181be0c6780Sdmick * /proc has possibly mucked with the syscall args. 1827c478bd9Sstevel@tonic-gate */ 183be0c6780Sdmick 1847c478bd9Sstevel@tonic-gate if (error) 1857c478bd9Sstevel@tonic-gate return (&sysent_err); /* use dummy handler */ 1867c478bd9Sstevel@tonic-gate } 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate /* 189be0c6780Sdmick * Fetch the system call arguments to the kernel stack copy used 190be0c6780Sdmick * for syscall handling. 1917c478bd9Sstevel@tonic-gate * Note: for loadable system calls the number of arguments required 1927c478bd9Sstevel@tonic-gate * may not be known at this point, and will be zero if the system call 1937c478bd9Sstevel@tonic-gate * was never loaded. Once the system call has been loaded, the number 1947c478bd9Sstevel@tonic-gate * of args is not allowed to be changed. 1957c478bd9Sstevel@tonic-gate */ 1967c478bd9Sstevel@tonic-gate if ((nargs = (uint_t)callp->sy_narg) != 0 && 1977c478bd9Sstevel@tonic-gate COPYIN_ARGS32(rp, argp, nargs)) { 1987c478bd9Sstevel@tonic-gate (void) set_errno(EFAULT); 1997c478bd9Sstevel@tonic-gate return (&sysent_err); /* use dummy handler */ 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate return (callp); /* return sysent entry for caller */ 2037c478bd9Sstevel@tonic-gate } 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate void 2067c478bd9Sstevel@tonic-gate syscall_exit(kthread_t *t, long rval1, long rval2) 2077c478bd9Sstevel@tonic-gate { 2087c478bd9Sstevel@tonic-gate /* 2097c478bd9Sstevel@tonic-gate * Handle signals and other post-call events if necessary. 2107c478bd9Sstevel@tonic-gate */ 2117c478bd9Sstevel@tonic-gate if ((t->t_post_sys_ast | syscalltrace) == 0) { 2127c478bd9Sstevel@tonic-gate klwp_t *lwp = ttolwp(t); 2137c478bd9Sstevel@tonic-gate struct regs *rp = lwptoregs(lwp); 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate /* 2167c478bd9Sstevel@tonic-gate * Normal return. 2177c478bd9Sstevel@tonic-gate * Clear error indication and set return values. 2187c478bd9Sstevel@tonic-gate */ 2197c478bd9Sstevel@tonic-gate rp->r_ps &= ~PS_C; /* reset carry bit */ 2207c478bd9Sstevel@tonic-gate rp->r_r0 = rval1; 2217c478bd9Sstevel@tonic-gate rp->r_r1 = rval2; 2227c478bd9Sstevel@tonic-gate lwp->lwp_state = LWP_USER; 2237c478bd9Sstevel@tonic-gate } else 2247c478bd9Sstevel@tonic-gate post_syscall(rval1, rval2); 2257c478bd9Sstevel@tonic-gate t->t_sysnum = 0; /* invalidate args */ 2267c478bd9Sstevel@tonic-gate } 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate /* 2297c478bd9Sstevel@tonic-gate * Perform pre-system-call processing, including stopping for tracing, 2307c478bd9Sstevel@tonic-gate * auditing, etc. 2317c478bd9Sstevel@tonic-gate * 2327c478bd9Sstevel@tonic-gate * This routine is called only if the t_pre_sys flag is set. Any condition 2337c478bd9Sstevel@tonic-gate * requiring pre-syscall handling must set the t_pre_sys flag. If the 2347c478bd9Sstevel@tonic-gate * condition is persistent, this routine will repost t_pre_sys. 2357c478bd9Sstevel@tonic-gate */ 2367c478bd9Sstevel@tonic-gate int 2377c478bd9Sstevel@tonic-gate pre_syscall() 2387c478bd9Sstevel@tonic-gate { 2397c478bd9Sstevel@tonic-gate kthread_t *t = curthread; 2407c478bd9Sstevel@tonic-gate unsigned code = t->t_sysnum; 2417c478bd9Sstevel@tonic-gate klwp_t *lwp = ttolwp(t); 2427c478bd9Sstevel@tonic-gate proc_t *p = ttoproc(t); 2437c478bd9Sstevel@tonic-gate int repost; 2447c478bd9Sstevel@tonic-gate 2457c478bd9Sstevel@tonic-gate t->t_pre_sys = repost = 0; /* clear pre-syscall processing flag */ 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate ASSERT(t->t_schedflag & TS_DONT_SWAP); 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate #if defined(DEBUG) 2507c478bd9Sstevel@tonic-gate /* 2517c478bd9Sstevel@tonic-gate * On the i386 kernel, lwp_ap points at the piece of the thread 2527c478bd9Sstevel@tonic-gate * stack that we copy the users arguments into. 2537c478bd9Sstevel@tonic-gate * 2547c478bd9Sstevel@tonic-gate * On the amd64 kernel, the syscall arguments in the rdi..r9 2557c478bd9Sstevel@tonic-gate * registers should be pointed at by lwp_ap. If the args need to 2567c478bd9Sstevel@tonic-gate * be copied so that those registers can be changed without losing 2577c478bd9Sstevel@tonic-gate * the ability to get the args for /proc, they can be saved by 2587c478bd9Sstevel@tonic-gate * save_syscall_args(), and lwp_ap will be restored by post_syscall(). 2597c478bd9Sstevel@tonic-gate */ 2607c478bd9Sstevel@tonic-gate if (lwp_getdatamodel(lwp) == DATAMODEL_NATIVE) { 2617c478bd9Sstevel@tonic-gate #if defined(_LP64) 2627c478bd9Sstevel@tonic-gate ASSERT(lwp->lwp_ap == (long *)&lwptoregs(lwp)->r_rdi); 2637c478bd9Sstevel@tonic-gate } else { 2647c478bd9Sstevel@tonic-gate #endif 2657c478bd9Sstevel@tonic-gate ASSERT((caddr_t)lwp->lwp_ap > t->t_stkbase && 2667c478bd9Sstevel@tonic-gate (caddr_t)lwp->lwp_ap < t->t_stk); 2677c478bd9Sstevel@tonic-gate } 2687c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate /* 2717c478bd9Sstevel@tonic-gate * Make sure the thread is holding the latest credentials for the 2727c478bd9Sstevel@tonic-gate * process. The credentials in the process right now apply to this 2737c478bd9Sstevel@tonic-gate * thread for the entire system call. 2747c478bd9Sstevel@tonic-gate */ 2757c478bd9Sstevel@tonic-gate if (t->t_cred != p->p_cred) { 2767c478bd9Sstevel@tonic-gate cred_t *oldcred = t->t_cred; 2777c478bd9Sstevel@tonic-gate /* 2787c478bd9Sstevel@tonic-gate * DTrace accesses t_cred in probe context. t_cred must 2797c478bd9Sstevel@tonic-gate * always be either NULL, or point to a valid, allocated cred 2807c478bd9Sstevel@tonic-gate * structure. 2817c478bd9Sstevel@tonic-gate */ 2827c478bd9Sstevel@tonic-gate t->t_cred = crgetcred(); 2837c478bd9Sstevel@tonic-gate crfree(oldcred); 2847c478bd9Sstevel@tonic-gate } 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate /* 2877c478bd9Sstevel@tonic-gate * From the proc(4) manual page: 2887c478bd9Sstevel@tonic-gate * When entry to a system call is being traced, the traced process 2897c478bd9Sstevel@tonic-gate * stops after having begun the call to the system but before the 2907c478bd9Sstevel@tonic-gate * system call arguments have been fetched from the process. 2917c478bd9Sstevel@tonic-gate */ 2927c478bd9Sstevel@tonic-gate if (PTOU(p)->u_systrap) { 2937c478bd9Sstevel@tonic-gate if (prismember(&PTOU(p)->u_entrymask, code)) { 2947c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 2957c478bd9Sstevel@tonic-gate /* 2967c478bd9Sstevel@tonic-gate * Recheck stop condition, now that lock is held. 2977c478bd9Sstevel@tonic-gate */ 2987c478bd9Sstevel@tonic-gate if (PTOU(p)->u_systrap && 2997c478bd9Sstevel@tonic-gate prismember(&PTOU(p)->u_entrymask, code)) { 3007c478bd9Sstevel@tonic-gate stop(PR_SYSENTRY, code); 301be0c6780Sdmick 3027c478bd9Sstevel@tonic-gate /* 303be0c6780Sdmick * /proc may have modified syscall args, 304be0c6780Sdmick * either in regs for amd64 or on ustack 305be0c6780Sdmick * for ia32. Either way, arrange to 306be0c6780Sdmick * copy them again, both for the syscall 307be0c6780Sdmick * handler and for other consumers in 308be0c6780Sdmick * post_syscall (like audit). Here, we 309be0c6780Sdmick * only do amd64, and just set lwp_ap 310be0c6780Sdmick * back to the kernel-entry stack copy; 311be0c6780Sdmick * the syscall ml code redoes 312be0c6780Sdmick * move-from-regs to set up for the 313be0c6780Sdmick * syscall handler after we return. For 314be0c6780Sdmick * ia32, save_syscall_args() below makes 315be0c6780Sdmick * an lwp_ap-accessible copy. 3167c478bd9Sstevel@tonic-gate */ 317be0c6780Sdmick #if defined(_LP64) 3187c478bd9Sstevel@tonic-gate if (lwp_getdatamodel(lwp) == DATAMODEL_NATIVE) { 3197c478bd9Sstevel@tonic-gate lwp->lwp_argsaved = 0; 3207c478bd9Sstevel@tonic-gate lwp->lwp_ap = 3217c478bd9Sstevel@tonic-gate (long *)&lwptoregs(lwp)->r_rdi; 3227c478bd9Sstevel@tonic-gate } 3237c478bd9Sstevel@tonic-gate #endif 3247c478bd9Sstevel@tonic-gate } 3257c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 3267c478bd9Sstevel@tonic-gate } 3277c478bd9Sstevel@tonic-gate repost = 1; 3287c478bd9Sstevel@tonic-gate } 3297c478bd9Sstevel@tonic-gate 330be0c6780Sdmick /* 331be0c6780Sdmick * ia32 kernel, or ia32 proc on amd64 kernel: keep args in 332be0c6780Sdmick * lwp_arg for post-syscall processing, regardless of whether 333be0c6780Sdmick * they might have been changed in /proc above. 334be0c6780Sdmick */ 335be0c6780Sdmick #if defined(_LP64) 336be0c6780Sdmick if (lwp_getdatamodel(lwp) != DATAMODEL_NATIVE) 337be0c6780Sdmick #endif 338be0c6780Sdmick (void) save_syscall_args(); 339be0c6780Sdmick 3407c478bd9Sstevel@tonic-gate if (lwp->lwp_sysabort) { 3417c478bd9Sstevel@tonic-gate /* 3427c478bd9Sstevel@tonic-gate * lwp_sysabort may have been set via /proc while the process 3437c478bd9Sstevel@tonic-gate * was stopped on PR_SYSENTRY. If so, abort the system call. 3447c478bd9Sstevel@tonic-gate * Override any error from the copyin() of the arguments. 3457c478bd9Sstevel@tonic-gate */ 3467c478bd9Sstevel@tonic-gate lwp->lwp_sysabort = 0; 3477c478bd9Sstevel@tonic-gate (void) set_errno(EINTR); /* forces post_sys */ 3487c478bd9Sstevel@tonic-gate t->t_pre_sys = 1; /* repost anyway */ 3497c478bd9Sstevel@tonic-gate return (1); /* don't do system call, return EINTR */ 3507c478bd9Sstevel@tonic-gate } 3517c478bd9Sstevel@tonic-gate 352005d3febSMarek Pospisil /* 353005d3febSMarek Pospisil * begin auditing for this syscall if the c2audit module is loaded 354005d3febSMarek Pospisil * and auditing is enabled 355005d3febSMarek Pospisil */ 356005d3febSMarek Pospisil if (audit_active == C2AUDIT_LOADED) { 357005d3febSMarek Pospisil uint32_t auditing = au_zone_getstate(NULL); 358005d3febSMarek Pospisil 359005d3febSMarek Pospisil if (auditing & AU_AUDIT_MASK) { 3607c478bd9Sstevel@tonic-gate int error; 361005d3febSMarek Pospisil if (error = audit_start(T_SYSCALL, code, auditing, \ 362005d3febSMarek Pospisil 0, lwp)) { 3637c478bd9Sstevel@tonic-gate t->t_pre_sys = 1; /* repost anyway */ 3647c478bd9Sstevel@tonic-gate (void) set_errno(error); 3657c478bd9Sstevel@tonic-gate return (1); 3667c478bd9Sstevel@tonic-gate } 3677c478bd9Sstevel@tonic-gate repost = 1; 3687c478bd9Sstevel@tonic-gate } 369005d3febSMarek Pospisil } 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate #ifndef NPROBE 3727c478bd9Sstevel@tonic-gate /* Kernel probe */ 3737c478bd9Sstevel@tonic-gate if (tnf_tracing_active) { 3747c478bd9Sstevel@tonic-gate TNF_PROBE_1(syscall_start, "syscall thread", /* CSTYLED */, 3757c478bd9Sstevel@tonic-gate tnf_sysnum, sysnum, t->t_sysnum); 3767c478bd9Sstevel@tonic-gate t->t_post_sys = 1; /* make sure post_syscall runs */ 3777c478bd9Sstevel@tonic-gate repost = 1; 3787c478bd9Sstevel@tonic-gate } 3797c478bd9Sstevel@tonic-gate #endif /* NPROBE */ 3807c478bd9Sstevel@tonic-gate 3817c478bd9Sstevel@tonic-gate #ifdef SYSCALLTRACE 3827c478bd9Sstevel@tonic-gate if (syscalltrace) { 3837c478bd9Sstevel@tonic-gate int i; 3847c478bd9Sstevel@tonic-gate long *ap; 3857c478bd9Sstevel@tonic-gate char *cp; 3867c478bd9Sstevel@tonic-gate char *sysname; 3877c478bd9Sstevel@tonic-gate struct sysent *callp; 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate if (code >= NSYSCALL) 3907c478bd9Sstevel@tonic-gate callp = &nosys_ent; /* nosys has no args */ 3917c478bd9Sstevel@tonic-gate else 3927c478bd9Sstevel@tonic-gate callp = LWP_GETSYSENT(lwp) + code; 3937c478bd9Sstevel@tonic-gate (void) save_syscall_args(); 3947c478bd9Sstevel@tonic-gate mutex_enter(&systrace_lock); 3957c478bd9Sstevel@tonic-gate printf("%d: ", p->p_pid); 3967c478bd9Sstevel@tonic-gate if (code >= NSYSCALL) 3977c478bd9Sstevel@tonic-gate printf("0x%x", code); 3987c478bd9Sstevel@tonic-gate else { 3997c478bd9Sstevel@tonic-gate sysname = mod_getsysname(code); 4007c478bd9Sstevel@tonic-gate printf("%s[0x%x/0x%p]", sysname == NULL ? "NULL" : 4017c478bd9Sstevel@tonic-gate sysname, code, callp->sy_callc); 4027c478bd9Sstevel@tonic-gate } 4037c478bd9Sstevel@tonic-gate cp = "("; 4047c478bd9Sstevel@tonic-gate for (i = 0, ap = lwp->lwp_ap; i < callp->sy_narg; i++, ap++) { 4057c478bd9Sstevel@tonic-gate printf("%s%lx", cp, *ap); 4067c478bd9Sstevel@tonic-gate cp = ", "; 4077c478bd9Sstevel@tonic-gate } 4087c478bd9Sstevel@tonic-gate if (i) 4097c478bd9Sstevel@tonic-gate printf(")"); 4107c478bd9Sstevel@tonic-gate printf(" %s id=0x%p\n", PTOU(p)->u_comm, curthread); 4117c478bd9Sstevel@tonic-gate mutex_exit(&systrace_lock); 4127c478bd9Sstevel@tonic-gate } 4137c478bd9Sstevel@tonic-gate #endif /* SYSCALLTRACE */ 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate /* 4167c478bd9Sstevel@tonic-gate * If there was a continuing reason for pre-syscall processing, 4177c478bd9Sstevel@tonic-gate * set the t_pre_sys flag for the next system call. 4187c478bd9Sstevel@tonic-gate */ 4197c478bd9Sstevel@tonic-gate if (repost) 4207c478bd9Sstevel@tonic-gate t->t_pre_sys = 1; 4217c478bd9Sstevel@tonic-gate lwp->lwp_error = 0; /* for old drivers */ 4227c478bd9Sstevel@tonic-gate lwp->lwp_badpriv = PRIV_NONE; 4237c478bd9Sstevel@tonic-gate return (0); 4247c478bd9Sstevel@tonic-gate } 4257c478bd9Sstevel@tonic-gate 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate /* 4287c478bd9Sstevel@tonic-gate * Post-syscall processing. Perform abnormal system call completion 4297c478bd9Sstevel@tonic-gate * actions such as /proc tracing, profiling, signals, preemption, etc. 4307c478bd9Sstevel@tonic-gate * 4317c478bd9Sstevel@tonic-gate * This routine is called only if t_post_sys, t_sig_check, or t_astflag is set. 4327c478bd9Sstevel@tonic-gate * Any condition requiring pre-syscall handling must set one of these. 4337c478bd9Sstevel@tonic-gate * If the condition is persistent, this routine will repost t_post_sys. 4347c478bd9Sstevel@tonic-gate */ 4357c478bd9Sstevel@tonic-gate void 4367c478bd9Sstevel@tonic-gate post_syscall(long rval1, long rval2) 4377c478bd9Sstevel@tonic-gate { 4387c478bd9Sstevel@tonic-gate kthread_t *t = curthread; 4397c478bd9Sstevel@tonic-gate klwp_t *lwp = ttolwp(t); 4407c478bd9Sstevel@tonic-gate proc_t *p = ttoproc(t); 4417c478bd9Sstevel@tonic-gate struct regs *rp = lwptoregs(lwp); 4427c478bd9Sstevel@tonic-gate uint_t error; 4437c478bd9Sstevel@tonic-gate uint_t code = t->t_sysnum; 4447c478bd9Sstevel@tonic-gate int repost = 0; 4457c478bd9Sstevel@tonic-gate int proc_stop = 0; /* non-zero if stopping */ 4467c478bd9Sstevel@tonic-gate int sigprof = 0; /* non-zero if sending SIGPROF */ 4477c478bd9Sstevel@tonic-gate 4487c478bd9Sstevel@tonic-gate t->t_post_sys = 0; 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate error = lwp->lwp_errno; 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate /* 4537c478bd9Sstevel@tonic-gate * Code can be zero if this is a new LWP returning after a forkall(), 4547c478bd9Sstevel@tonic-gate * other than the one which matches the one in the parent which called 4557c478bd9Sstevel@tonic-gate * forkall(). In these LWPs, skip most of post-syscall activity. 4567c478bd9Sstevel@tonic-gate */ 4577c478bd9Sstevel@tonic-gate if (code == 0) 4587c478bd9Sstevel@tonic-gate goto sig_check; 4598efd794bSsudheer /* 4608efd794bSsudheer * If the trace flag is set, mark the lwp to take a single-step trap 4618efd794bSsudheer * on return to user level (below). The x86 lcall interface and 4628efd794bSsudheer * sysenter has already done this, and turned off the flag, but 4638efd794bSsudheer * amd64 syscall interface has not. 4648efd794bSsudheer */ 4658efd794bSsudheer if (rp->r_ps & PS_T) { 4668efd794bSsudheer lwp->lwp_pcb.pcb_flags |= DEBUG_PENDING; 4678efd794bSsudheer rp->r_ps &= ~PS_T; 468d8aa0f5aSsudheer aston(curthread); 4698efd794bSsudheer } 470005d3febSMarek Pospisil 471005d3febSMarek Pospisil /* put out audit record for this syscall */ 472005d3febSMarek Pospisil if (AU_AUDITING()) { 4737c478bd9Sstevel@tonic-gate rval_t rval; 4747c478bd9Sstevel@tonic-gate 4757c478bd9Sstevel@tonic-gate /* XX64 -- truncation of 64-bit return values? */ 4767c478bd9Sstevel@tonic-gate rval.r_val1 = (int)rval1; 4777c478bd9Sstevel@tonic-gate rval.r_val2 = (int)rval2; 4787c478bd9Sstevel@tonic-gate audit_finish(T_SYSCALL, code, error, &rval); 4797c478bd9Sstevel@tonic-gate repost = 1; 4807c478bd9Sstevel@tonic-gate } 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate if (curthread->t_pdmsg != NULL) { 4837c478bd9Sstevel@tonic-gate char *m = curthread->t_pdmsg; 4847c478bd9Sstevel@tonic-gate 4857c478bd9Sstevel@tonic-gate uprintf("%s", m); 4867c478bd9Sstevel@tonic-gate kmem_free(m, strlen(m) + 1); 4877c478bd9Sstevel@tonic-gate curthread->t_pdmsg = NULL; 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate /* 4917c478bd9Sstevel@tonic-gate * If we're going to stop for /proc tracing, set the flag and 4927c478bd9Sstevel@tonic-gate * save the arguments so that the return values don't smash them. 4937c478bd9Sstevel@tonic-gate */ 4947c478bd9Sstevel@tonic-gate if (PTOU(p)->u_systrap) { 4957c478bd9Sstevel@tonic-gate if (prismember(&PTOU(p)->u_exitmask, code)) { 4967c478bd9Sstevel@tonic-gate if (lwp_getdatamodel(lwp) == DATAMODEL_LP64) 4977c478bd9Sstevel@tonic-gate (void) save_syscall_args(); 4987c478bd9Sstevel@tonic-gate proc_stop = 1; 4997c478bd9Sstevel@tonic-gate } 5007c478bd9Sstevel@tonic-gate repost = 1; 5017c478bd9Sstevel@tonic-gate } 5027c478bd9Sstevel@tonic-gate 5037c478bd9Sstevel@tonic-gate /* 5047c478bd9Sstevel@tonic-gate * Similarly check to see if SIGPROF might be sent. 5057c478bd9Sstevel@tonic-gate */ 5067c478bd9Sstevel@tonic-gate if (curthread->t_rprof != NULL && 5077c478bd9Sstevel@tonic-gate curthread->t_rprof->rp_anystate != 0) { 5087c478bd9Sstevel@tonic-gate if (lwp_getdatamodel(lwp) == DATAMODEL_LP64) 5097c478bd9Sstevel@tonic-gate (void) save_syscall_args(); 5107c478bd9Sstevel@tonic-gate sigprof = 1; 5117c478bd9Sstevel@tonic-gate } 5127c478bd9Sstevel@tonic-gate 5137c478bd9Sstevel@tonic-gate if (lwp->lwp_eosys == NORMALRETURN) { 5147c478bd9Sstevel@tonic-gate if (error == 0) { 5157c478bd9Sstevel@tonic-gate #ifdef SYSCALLTRACE 5167c478bd9Sstevel@tonic-gate if (syscalltrace) { 5177c478bd9Sstevel@tonic-gate mutex_enter(&systrace_lock); 5187c478bd9Sstevel@tonic-gate printf( 5197c478bd9Sstevel@tonic-gate "%d: r_val1=0x%lx, r_val2=0x%lx, id 0x%p\n", 5207c478bd9Sstevel@tonic-gate p->p_pid, rval1, rval2, curthread); 5217c478bd9Sstevel@tonic-gate mutex_exit(&systrace_lock); 5227c478bd9Sstevel@tonic-gate } 5237c478bd9Sstevel@tonic-gate #endif /* SYSCALLTRACE */ 5247c478bd9Sstevel@tonic-gate rp->r_ps &= ~PS_C; 5257c478bd9Sstevel@tonic-gate rp->r_r0 = rval1; 5267c478bd9Sstevel@tonic-gate rp->r_r1 = rval2; 5277c478bd9Sstevel@tonic-gate } else { 5287c478bd9Sstevel@tonic-gate int sig; 5297c478bd9Sstevel@tonic-gate #ifdef SYSCALLTRACE 5307c478bd9Sstevel@tonic-gate if (syscalltrace) { 5317c478bd9Sstevel@tonic-gate mutex_enter(&systrace_lock); 5327c478bd9Sstevel@tonic-gate printf("%d: error=%d, id 0x%p\n", 5337c478bd9Sstevel@tonic-gate p->p_pid, error, curthread); 5347c478bd9Sstevel@tonic-gate mutex_exit(&systrace_lock); 5357c478bd9Sstevel@tonic-gate } 5367c478bd9Sstevel@tonic-gate #endif /* SYSCALLTRACE */ 5377c478bd9Sstevel@tonic-gate if (error == EINTR && t->t_activefd.a_stale) 5387c478bd9Sstevel@tonic-gate error = EBADF; 5397c478bd9Sstevel@tonic-gate if (error == EINTR && 5407c478bd9Sstevel@tonic-gate (sig = lwp->lwp_cursig) != 0 && 5417c478bd9Sstevel@tonic-gate sigismember(&PTOU(p)->u_sigrestart, sig) && 5427c478bd9Sstevel@tonic-gate PTOU(p)->u_signal[sig - 1] != SIG_DFL && 5437c478bd9Sstevel@tonic-gate PTOU(p)->u_signal[sig - 1] != SIG_IGN) 5447c478bd9Sstevel@tonic-gate error = ERESTART; 5457c478bd9Sstevel@tonic-gate rp->r_r0 = error; 5467c478bd9Sstevel@tonic-gate rp->r_ps |= PS_C; 5477c478bd9Sstevel@tonic-gate } 5487c478bd9Sstevel@tonic-gate } 5497c478bd9Sstevel@tonic-gate 5507c478bd9Sstevel@tonic-gate /* 5517c478bd9Sstevel@tonic-gate * From the proc(4) manual page: 5527c478bd9Sstevel@tonic-gate * When exit from a system call is being traced, the traced process 5537c478bd9Sstevel@tonic-gate * stops on completion of the system call just prior to checking for 5547c478bd9Sstevel@tonic-gate * signals and returning to user level. At this point all return 5557c478bd9Sstevel@tonic-gate * values have been stored into the traced process's saved registers. 5567c478bd9Sstevel@tonic-gate */ 5577c478bd9Sstevel@tonic-gate if (proc_stop) { 5587c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 5597c478bd9Sstevel@tonic-gate if (PTOU(p)->u_systrap && 5607c478bd9Sstevel@tonic-gate prismember(&PTOU(p)->u_exitmask, code)) 5617c478bd9Sstevel@tonic-gate stop(PR_SYSEXIT, code); 5627c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 5637c478bd9Sstevel@tonic-gate } 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate /* 5667c478bd9Sstevel@tonic-gate * If we are the parent returning from a successful 5677c478bd9Sstevel@tonic-gate * vfork, wait for the child to exec or exit. 5687c478bd9Sstevel@tonic-gate * This code must be here and not in the bowels of the system 5697c478bd9Sstevel@tonic-gate * so that /proc can intercept exit from vfork in a timely way. 5707c478bd9Sstevel@tonic-gate */ 5718d186f16Sraf if (t->t_flag & T_VFPARENT) { 572657b1f3dSraf ASSERT(code == SYS_vfork || code == SYS_forksys); 573657b1f3dSraf ASSERT(rp->r_r1 == 0 && error == 0); 5747c478bd9Sstevel@tonic-gate vfwait((pid_t)rval1); 5758d186f16Sraf t->t_flag &= ~T_VFPARENT; 576657b1f3dSraf } 5777c478bd9Sstevel@tonic-gate 5787c478bd9Sstevel@tonic-gate /* 5797c478bd9Sstevel@tonic-gate * If profiling is active, bill the current PC in user-land 5807c478bd9Sstevel@tonic-gate * and keep reposting until profiling is disabled. 5817c478bd9Sstevel@tonic-gate */ 5827c478bd9Sstevel@tonic-gate if (p->p_prof.pr_scale) { 5837c478bd9Sstevel@tonic-gate if (lwp->lwp_oweupc) 5847c478bd9Sstevel@tonic-gate profil_tick(rp->r_pc); 5857c478bd9Sstevel@tonic-gate repost = 1; 5867c478bd9Sstevel@tonic-gate } 5877c478bd9Sstevel@tonic-gate 5887c478bd9Sstevel@tonic-gate sig_check: 5897c478bd9Sstevel@tonic-gate /* 5907c478bd9Sstevel@tonic-gate * Reset flag for next time. 5917c478bd9Sstevel@tonic-gate * We must do this after stopping on PR_SYSEXIT 5927c478bd9Sstevel@tonic-gate * because /proc uses the information in lwp_eosys. 5937c478bd9Sstevel@tonic-gate */ 5947c478bd9Sstevel@tonic-gate lwp->lwp_eosys = NORMALRETURN; 5957c478bd9Sstevel@tonic-gate clear_stale_fd(); 596c4978b50Sraf t->t_flag &= ~T_FORKALL; 5977c478bd9Sstevel@tonic-gate 598d8aa0f5aSsudheer if (t->t_astflag | t->t_sig_check) { 599d8aa0f5aSsudheer /* 600d8aa0f5aSsudheer * Turn off the AST flag before checking all the conditions that 601d8aa0f5aSsudheer * may have caused an AST. This flag is on whenever a signal or 602d8aa0f5aSsudheer * unusual condition should be handled after the next trap or 603d8aa0f5aSsudheer * syscall. 604d8aa0f5aSsudheer */ 605d8aa0f5aSsudheer astoff(t); 6067c478bd9Sstevel@tonic-gate /* 6077c478bd9Sstevel@tonic-gate * If a single-step trap occurred on a syscall (see trap()) 6087c478bd9Sstevel@tonic-gate * recognize it now. Do this before checking for signals 6097c478bd9Sstevel@tonic-gate * because deferred_singlestep_trap() may generate a SIGTRAP to 6107c478bd9Sstevel@tonic-gate * the LWP or may otherwise mark the LWP to call issig(FORREAL). 6117c478bd9Sstevel@tonic-gate */ 6127c478bd9Sstevel@tonic-gate if (lwp->lwp_pcb.pcb_flags & DEBUG_PENDING) 6137c478bd9Sstevel@tonic-gate deferred_singlestep_trap((caddr_t)rp->r_pc); 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate t->t_sig_check = 0; 6167c478bd9Sstevel@tonic-gate 617efd37614Sdv142724 /* 618efd37614Sdv142724 * The following check is legal for the following reasons: 619efd37614Sdv142724 * 1) The thread we are checking, is ourselves, so there is 620efd37614Sdv142724 * no way the proc can go away. 621efd37614Sdv142724 * 2) The only time we need to be protected by the 622efd37614Sdv142724 * lock is if the binding is changed. 623efd37614Sdv142724 * 624efd37614Sdv142724 * Note we will still take the lock and check the binding 625efd37614Sdv142724 * if the condition was true without the lock held. This 626efd37614Sdv142724 * prevents lock contention among threads owned by the 627efd37614Sdv142724 * same proc. 628efd37614Sdv142724 */ 629efd37614Sdv142724 630efd37614Sdv142724 if (curthread->t_proc_flag & TP_CHANGEBIND) { 6317c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 6327c478bd9Sstevel@tonic-gate if (curthread->t_proc_flag & TP_CHANGEBIND) { 6337c478bd9Sstevel@tonic-gate timer_lwpbind(); 6347c478bd9Sstevel@tonic-gate curthread->t_proc_flag &= ~TP_CHANGEBIND; 6357c478bd9Sstevel@tonic-gate } 6367c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 637efd37614Sdv142724 } 6387c478bd9Sstevel@tonic-gate 6397c478bd9Sstevel@tonic-gate /* 6407c478bd9Sstevel@tonic-gate * for kaio requests on the special kaio poll queue, 6417c478bd9Sstevel@tonic-gate * copyout their results to user memory. 6427c478bd9Sstevel@tonic-gate */ 6437c478bd9Sstevel@tonic-gate if (p->p_aio) 6447c478bd9Sstevel@tonic-gate aio_cleanup(0); 6457c478bd9Sstevel@tonic-gate /* 6467c478bd9Sstevel@tonic-gate * If this LWP was asked to hold, call holdlwp(), which will 6477c478bd9Sstevel@tonic-gate * stop. holdlwps() sets this up and calls pokelwps() which 6487c478bd9Sstevel@tonic-gate * sets the AST flag. 6497c478bd9Sstevel@tonic-gate * 6507c478bd9Sstevel@tonic-gate * Also check TP_EXITLWP, since this is used by fresh new LWPs 6517c478bd9Sstevel@tonic-gate * through lwp_rtt(). That flag is set if the lwp_create(2) 6527c478bd9Sstevel@tonic-gate * syscall failed after creating the LWP. 6537c478bd9Sstevel@tonic-gate */ 6547c478bd9Sstevel@tonic-gate if (ISHOLD(p) || (t->t_proc_flag & TP_EXITLWP)) 6557c478bd9Sstevel@tonic-gate holdlwp(); 6567c478bd9Sstevel@tonic-gate 6577c478bd9Sstevel@tonic-gate /* 6587c478bd9Sstevel@tonic-gate * All code that sets signals and makes ISSIG_PENDING 6597c478bd9Sstevel@tonic-gate * evaluate true must set t_sig_check afterwards. 6607c478bd9Sstevel@tonic-gate */ 6617c478bd9Sstevel@tonic-gate if (ISSIG_PENDING(t, lwp, p)) { 6627c478bd9Sstevel@tonic-gate if (issig(FORREAL)) 6637c478bd9Sstevel@tonic-gate psig(); 6647c478bd9Sstevel@tonic-gate t->t_sig_check = 1; /* recheck next time */ 6657c478bd9Sstevel@tonic-gate } 6667c478bd9Sstevel@tonic-gate 6677c478bd9Sstevel@tonic-gate if (sigprof) { 668e0cf54a5SRoger A. Faulkner int nargs = (code > 0 && code < NSYSCALL)? 669e0cf54a5SRoger A. Faulkner LWP_GETSYSENT(lwp)[code].sy_narg : 0; 670e0cf54a5SRoger A. Faulkner realsigprof(code, nargs, error); 6717c478bd9Sstevel@tonic-gate t->t_sig_check = 1; /* recheck next time */ 6727c478bd9Sstevel@tonic-gate } 6737c478bd9Sstevel@tonic-gate 6747c478bd9Sstevel@tonic-gate /* 6757c478bd9Sstevel@tonic-gate * If a performance counter overflow interrupt was 6767c478bd9Sstevel@tonic-gate * delivered *during* the syscall, then re-enable the 6777c478bd9Sstevel@tonic-gate * AST so that we take a trip through trap() to cause 6787c478bd9Sstevel@tonic-gate * the SIGEMT to be delivered. 6797c478bd9Sstevel@tonic-gate */ 6807c478bd9Sstevel@tonic-gate if (lwp->lwp_pcb.pcb_flags & CPC_OVERFLOW) 6817c478bd9Sstevel@tonic-gate aston(t); 68265a89a64Smarx 68365a89a64Smarx /* 68465a89a64Smarx * /proc can't enable/disable the trace bit itself 68565a89a64Smarx * because that could race with the call gate used by 68665a89a64Smarx * system calls via "lcall". If that happened, an 68765a89a64Smarx * invalid EFLAGS would result. prstep()/prnostep() 68865a89a64Smarx * therefore schedule an AST for the purpose. 68965a89a64Smarx */ 69065a89a64Smarx if (lwp->lwp_pcb.pcb_flags & REQUEST_STEP) { 69165a89a64Smarx lwp->lwp_pcb.pcb_flags &= ~REQUEST_STEP; 69265a89a64Smarx rp->r_ps |= PS_T; 69365a89a64Smarx } 69465a89a64Smarx if (lwp->lwp_pcb.pcb_flags & REQUEST_NOSTEP) { 69565a89a64Smarx lwp->lwp_pcb.pcb_flags &= ~REQUEST_NOSTEP; 69665a89a64Smarx rp->r_ps &= ~PS_T; 69765a89a64Smarx } 6987c478bd9Sstevel@tonic-gate } 6997c478bd9Sstevel@tonic-gate 7007c478bd9Sstevel@tonic-gate lwp->lwp_errno = 0; /* clear error for next time */ 7017c478bd9Sstevel@tonic-gate 7027c478bd9Sstevel@tonic-gate #ifndef NPROBE 7037c478bd9Sstevel@tonic-gate /* Kernel probe */ 7047c478bd9Sstevel@tonic-gate if (tnf_tracing_active) { 7057c478bd9Sstevel@tonic-gate TNF_PROBE_3(syscall_end, "syscall thread", /* CSTYLED */, 7067c478bd9Sstevel@tonic-gate tnf_long, rval1, rval1, 7077c478bd9Sstevel@tonic-gate tnf_long, rval2, rval2, 7087c478bd9Sstevel@tonic-gate tnf_long, errno, (long)error); 7097c478bd9Sstevel@tonic-gate repost = 1; 7107c478bd9Sstevel@tonic-gate } 7117c478bd9Sstevel@tonic-gate #endif /* NPROBE */ 7127c478bd9Sstevel@tonic-gate 7137c478bd9Sstevel@tonic-gate /* 7147c478bd9Sstevel@tonic-gate * Set state to LWP_USER here so preempt won't give us a kernel 7157c478bd9Sstevel@tonic-gate * priority if it occurs after this point. Call CL_TRAPRET() to 7167c478bd9Sstevel@tonic-gate * restore the user-level priority. 7177c478bd9Sstevel@tonic-gate * 7187c478bd9Sstevel@tonic-gate * It is important that no locks (other than spinlocks) be entered 7197c478bd9Sstevel@tonic-gate * after this point before returning to user mode (unless lwp_state 7207c478bd9Sstevel@tonic-gate * is set back to LWP_SYS). 7217c478bd9Sstevel@tonic-gate * 7227c478bd9Sstevel@tonic-gate * XXX Sampled times past this point are charged to the user. 7237c478bd9Sstevel@tonic-gate */ 7247c478bd9Sstevel@tonic-gate lwp->lwp_state = LWP_USER; 7257c478bd9Sstevel@tonic-gate 7267c478bd9Sstevel@tonic-gate if (t->t_trapret) { 7277c478bd9Sstevel@tonic-gate t->t_trapret = 0; 7287c478bd9Sstevel@tonic-gate thread_lock(t); 7297c478bd9Sstevel@tonic-gate CL_TRAPRET(t); 7307c478bd9Sstevel@tonic-gate thread_unlock(t); 7317c478bd9Sstevel@tonic-gate } 732c97ad5cdSakolb if (CPU->cpu_runrun || t->t_schedflag & TS_ANYWAITQ) 7337c478bd9Sstevel@tonic-gate preempt(); 73407a48826SRoger A. Faulkner prunstop(); 7357c478bd9Sstevel@tonic-gate 7367c478bd9Sstevel@tonic-gate lwp->lwp_errno = 0; /* clear error for next time */ 7377c478bd9Sstevel@tonic-gate 7387c478bd9Sstevel@tonic-gate /* 7397c478bd9Sstevel@tonic-gate * The thread lock must be held in order to clear sysnum and reset 7407c478bd9Sstevel@tonic-gate * lwp_ap atomically with respect to other threads in the system that 7417c478bd9Sstevel@tonic-gate * may be looking at the args via lwp_ap from get_syscall_args(). 7427c478bd9Sstevel@tonic-gate */ 7437c478bd9Sstevel@tonic-gate 7447c478bd9Sstevel@tonic-gate thread_lock(t); 7457c478bd9Sstevel@tonic-gate t->t_sysnum = 0; /* no longer in a system call */ 7467c478bd9Sstevel@tonic-gate 7477c478bd9Sstevel@tonic-gate if (lwp_getdatamodel(lwp) == DATAMODEL_NATIVE) { 7487c478bd9Sstevel@tonic-gate #if defined(_LP64) 7497c478bd9Sstevel@tonic-gate /* 7507c478bd9Sstevel@tonic-gate * In case the args were copied to the lwp, reset the 7517c478bd9Sstevel@tonic-gate * pointer so the next syscall will have the right 7527c478bd9Sstevel@tonic-gate * lwp_ap pointer. 7537c478bd9Sstevel@tonic-gate */ 7547c478bd9Sstevel@tonic-gate lwp->lwp_ap = (long *)&rp->r_rdi; 7557c478bd9Sstevel@tonic-gate } else { 7567c478bd9Sstevel@tonic-gate #endif 7577c478bd9Sstevel@tonic-gate lwp->lwp_ap = NULL; /* reset on every syscall entry */ 7587c478bd9Sstevel@tonic-gate } 7597c478bd9Sstevel@tonic-gate thread_unlock(t); 7607c478bd9Sstevel@tonic-gate 7617c478bd9Sstevel@tonic-gate lwp->lwp_argsaved = 0; 7627c478bd9Sstevel@tonic-gate 7637c478bd9Sstevel@tonic-gate /* 7647c478bd9Sstevel@tonic-gate * If there was a continuing reason for post-syscall processing, 7657c478bd9Sstevel@tonic-gate * set the t_post_sys flag for the next system call. 7667c478bd9Sstevel@tonic-gate */ 7677c478bd9Sstevel@tonic-gate if (repost) 7687c478bd9Sstevel@tonic-gate t->t_post_sys = 1; 7697c478bd9Sstevel@tonic-gate 7707c478bd9Sstevel@tonic-gate /* 7717c478bd9Sstevel@tonic-gate * If there is a ustack registered for this lwp, and the stack rlimit 7727c478bd9Sstevel@tonic-gate * has been altered, read in the ustack. If the saved stack rlimit 7737c478bd9Sstevel@tonic-gate * matches the bounds of the ustack, update the ustack to reflect 7747c478bd9Sstevel@tonic-gate * the new rlimit. If the new stack rlimit is RLIM_INFINITY, disable 7757c478bd9Sstevel@tonic-gate * stack checking by setting the size to 0. 7767c478bd9Sstevel@tonic-gate */ 7777c478bd9Sstevel@tonic-gate if (lwp->lwp_ustack != 0 && lwp->lwp_old_stk_ctl != 0) { 7787c478bd9Sstevel@tonic-gate rlim64_t new_size; 7797c478bd9Sstevel@tonic-gate caddr_t top; 7807c478bd9Sstevel@tonic-gate stack_t stk; 7817c478bd9Sstevel@tonic-gate struct rlimit64 rl; 7827c478bd9Sstevel@tonic-gate 7837c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 7847c478bd9Sstevel@tonic-gate new_size = p->p_stk_ctl; 7857c478bd9Sstevel@tonic-gate top = p->p_usrstack; 7867c478bd9Sstevel@tonic-gate (void) rctl_rlimit_get(rctlproc_legacy[RLIMIT_STACK], p, &rl); 7877c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 7887c478bd9Sstevel@tonic-gate 7897c478bd9Sstevel@tonic-gate if (rl.rlim_cur == RLIM64_INFINITY) 7907c478bd9Sstevel@tonic-gate new_size = 0; 7917c478bd9Sstevel@tonic-gate 7927c478bd9Sstevel@tonic-gate if (copyin((stack_t *)lwp->lwp_ustack, &stk, 7937c478bd9Sstevel@tonic-gate sizeof (stack_t)) == 0 && 7947c478bd9Sstevel@tonic-gate (stk.ss_size == lwp->lwp_old_stk_ctl || 7957c478bd9Sstevel@tonic-gate stk.ss_size == 0) && 7967c478bd9Sstevel@tonic-gate stk.ss_sp == top - stk.ss_size) { 7977c478bd9Sstevel@tonic-gate stk.ss_sp = (void *)((uintptr_t)stk.ss_sp + 7987c478bd9Sstevel@tonic-gate stk.ss_size - (uintptr_t)new_size); 7997c478bd9Sstevel@tonic-gate stk.ss_size = new_size; 8007c478bd9Sstevel@tonic-gate 8017c478bd9Sstevel@tonic-gate (void) copyout(&stk, (stack_t *)lwp->lwp_ustack, 8027c478bd9Sstevel@tonic-gate sizeof (stack_t)); 8037c478bd9Sstevel@tonic-gate } 8047c478bd9Sstevel@tonic-gate 8057c478bd9Sstevel@tonic-gate lwp->lwp_old_stk_ctl = 0; 8067c478bd9Sstevel@tonic-gate } 8077c478bd9Sstevel@tonic-gate } 8087c478bd9Sstevel@tonic-gate 8097c478bd9Sstevel@tonic-gate /* 8107c478bd9Sstevel@tonic-gate * Called from post_syscall() when a deferred singlestep is to be taken. 8117c478bd9Sstevel@tonic-gate */ 812d8aa0f5aSsudheer void 8137c478bd9Sstevel@tonic-gate deferred_singlestep_trap(caddr_t pc) 8147c478bd9Sstevel@tonic-gate { 8157c478bd9Sstevel@tonic-gate proc_t *p = ttoproc(curthread); 8167c478bd9Sstevel@tonic-gate klwp_t *lwp = ttolwp(curthread); 8177c478bd9Sstevel@tonic-gate pcb_t *pcb = &lwp->lwp_pcb; 8187c478bd9Sstevel@tonic-gate uint_t fault = 0; 8197c478bd9Sstevel@tonic-gate k_siginfo_t siginfo; 8207c478bd9Sstevel@tonic-gate 8217c478bd9Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo)); 8227c478bd9Sstevel@tonic-gate 8237c478bd9Sstevel@tonic-gate /* 8247c478bd9Sstevel@tonic-gate * If both NORMAL_STEP and WATCH_STEP are in 8259acbbeafSnn35248 * effect, give precedence to WATCH_STEP. 8267c478bd9Sstevel@tonic-gate * If neither is set, user must have set the 8277c478bd9Sstevel@tonic-gate * PS_T bit in %efl; treat this as NORMAL_STEP. 8287c478bd9Sstevel@tonic-gate */ 8299acbbeafSnn35248 if ((fault = undo_watch_step(&siginfo)) == 0 && 8309acbbeafSnn35248 ((pcb->pcb_flags & NORMAL_STEP) || 8319acbbeafSnn35248 !(pcb->pcb_flags & WATCH_STEP))) { 8327c478bd9Sstevel@tonic-gate siginfo.si_signo = SIGTRAP; 8337c478bd9Sstevel@tonic-gate siginfo.si_code = TRAP_TRACE; 8347c478bd9Sstevel@tonic-gate siginfo.si_addr = pc; 8357c478bd9Sstevel@tonic-gate fault = FLTTRACE; 8367c478bd9Sstevel@tonic-gate } 8377c478bd9Sstevel@tonic-gate pcb->pcb_flags &= ~(DEBUG_PENDING|NORMAL_STEP|WATCH_STEP); 8387c478bd9Sstevel@tonic-gate 8397c478bd9Sstevel@tonic-gate if (fault) { 8407c478bd9Sstevel@tonic-gate /* 8417c478bd9Sstevel@tonic-gate * Remember the fault and fault adddress 8427c478bd9Sstevel@tonic-gate * for real-time (SIGPROF) profiling. 8437c478bd9Sstevel@tonic-gate */ 8447c478bd9Sstevel@tonic-gate lwp->lwp_lastfault = fault; 8457c478bd9Sstevel@tonic-gate lwp->lwp_lastfaddr = siginfo.si_addr; 8467c478bd9Sstevel@tonic-gate /* 8477c478bd9Sstevel@tonic-gate * If a debugger has declared this fault to be an 8487c478bd9Sstevel@tonic-gate * event of interest, stop the lwp. Otherwise just 8497c478bd9Sstevel@tonic-gate * deliver the associated signal. 8507c478bd9Sstevel@tonic-gate */ 8517c478bd9Sstevel@tonic-gate if (prismember(&p->p_fltmask, fault) && 8527c478bd9Sstevel@tonic-gate stop_on_fault(fault, &siginfo) == 0) 8537c478bd9Sstevel@tonic-gate siginfo.si_signo = 0; 8547c478bd9Sstevel@tonic-gate } 8557c478bd9Sstevel@tonic-gate 8567c478bd9Sstevel@tonic-gate if (siginfo.si_signo) 8577c478bd9Sstevel@tonic-gate trapsig(&siginfo, 1); 8587c478bd9Sstevel@tonic-gate } 8597c478bd9Sstevel@tonic-gate 8607c478bd9Sstevel@tonic-gate /* 8617c478bd9Sstevel@tonic-gate * nonexistent system call-- signal lwp (may want to handle it) 8627c478bd9Sstevel@tonic-gate * flag error if lwp won't see signal immediately 8637c478bd9Sstevel@tonic-gate */ 8647c478bd9Sstevel@tonic-gate int64_t 8657c478bd9Sstevel@tonic-gate nosys() 8667c478bd9Sstevel@tonic-gate { 8677c478bd9Sstevel@tonic-gate tsignal(curthread, SIGSYS); 8687c478bd9Sstevel@tonic-gate return (set_errno(ENOSYS)); 8697c478bd9Sstevel@tonic-gate } 8707c478bd9Sstevel@tonic-gate 8717c478bd9Sstevel@tonic-gate /* 8727c478bd9Sstevel@tonic-gate * Execute a 32-bit system call on behalf of the current thread. 8737c478bd9Sstevel@tonic-gate */ 8747c478bd9Sstevel@tonic-gate void 8757c478bd9Sstevel@tonic-gate dosyscall(void) 8767c478bd9Sstevel@tonic-gate { 8777c478bd9Sstevel@tonic-gate /* 8787c478bd9Sstevel@tonic-gate * Need space on the stack to store syscall arguments. 8797c478bd9Sstevel@tonic-gate */ 8807c478bd9Sstevel@tonic-gate long syscall_args[MAXSYSARGS]; 8817c478bd9Sstevel@tonic-gate struct sysent *se; 8827c478bd9Sstevel@tonic-gate int64_t ret; 8837c478bd9Sstevel@tonic-gate 8847c478bd9Sstevel@tonic-gate syscall_mstate(LMS_TRAP, LMS_SYSTEM); 8857c478bd9Sstevel@tonic-gate 8867c478bd9Sstevel@tonic-gate ASSERT(curproc->p_model == DATAMODEL_ILP32); 8877c478bd9Sstevel@tonic-gate 8887c478bd9Sstevel@tonic-gate CPU_STATS_ENTER_K(); 8897c478bd9Sstevel@tonic-gate CPU_STATS_ADDQ(CPU, sys, syscall, 1); 8907c478bd9Sstevel@tonic-gate CPU_STATS_EXIT_K(); 8917c478bd9Sstevel@tonic-gate 8927c478bd9Sstevel@tonic-gate se = syscall_entry(curthread, syscall_args); 8937c478bd9Sstevel@tonic-gate 8947c478bd9Sstevel@tonic-gate /* 8957c478bd9Sstevel@tonic-gate * syscall_entry() copied all 8 arguments into syscall_args. 8967c478bd9Sstevel@tonic-gate */ 8977c478bd9Sstevel@tonic-gate ret = se->sy_callc(syscall_args[0], syscall_args[1], syscall_args[2], 8987c478bd9Sstevel@tonic-gate syscall_args[3], syscall_args[4], syscall_args[5], syscall_args[6], 8997c478bd9Sstevel@tonic-gate syscall_args[7]); 9007c478bd9Sstevel@tonic-gate 9017c478bd9Sstevel@tonic-gate syscall_exit(curthread, (int)ret & 0xffffffffu, (int)(ret >> 32)); 9027c478bd9Sstevel@tonic-gate syscall_mstate(LMS_SYSTEM, LMS_TRAP); 9037c478bd9Sstevel@tonic-gate } 9047c478bd9Sstevel@tonic-gate 9057c478bd9Sstevel@tonic-gate /* 9067c478bd9Sstevel@tonic-gate * Get the arguments to the current system call. See comment atop 9077c478bd9Sstevel@tonic-gate * save_syscall_args() regarding lwp_ap usage. 9087c478bd9Sstevel@tonic-gate */ 9097c478bd9Sstevel@tonic-gate 9107c478bd9Sstevel@tonic-gate uint_t 9117c478bd9Sstevel@tonic-gate get_syscall_args(klwp_t *lwp, long *argp, int *nargsp) 9127c478bd9Sstevel@tonic-gate { 9137c478bd9Sstevel@tonic-gate kthread_t *t = lwptot(lwp); 9147c478bd9Sstevel@tonic-gate ulong_t mask = 0xfffffffful; 9157c478bd9Sstevel@tonic-gate uint_t code; 9167c478bd9Sstevel@tonic-gate long *ap; 9177c478bd9Sstevel@tonic-gate int nargs; 9187c478bd9Sstevel@tonic-gate 9197c478bd9Sstevel@tonic-gate #if defined(_LP64) 9207c478bd9Sstevel@tonic-gate if (lwp_getdatamodel(lwp) == DATAMODEL_LP64) 9217c478bd9Sstevel@tonic-gate mask = 0xfffffffffffffffful; 9227c478bd9Sstevel@tonic-gate #endif 9237c478bd9Sstevel@tonic-gate 9247c478bd9Sstevel@tonic-gate /* 9257c478bd9Sstevel@tonic-gate * The thread lock must be held while looking at the arguments to ensure 9267c478bd9Sstevel@tonic-gate * they don't go away via post_syscall(). 9277c478bd9Sstevel@tonic-gate * get_syscall_args() is the only routine to read them which is callable 9287c478bd9Sstevel@tonic-gate * outside the LWP in question and hence the only one that must be 9297c478bd9Sstevel@tonic-gate * synchronized in this manner. 9307c478bd9Sstevel@tonic-gate */ 9317c478bd9Sstevel@tonic-gate thread_lock(t); 9327c478bd9Sstevel@tonic-gate 9337c478bd9Sstevel@tonic-gate code = t->t_sysnum; 9347c478bd9Sstevel@tonic-gate ap = lwp->lwp_ap; 9357c478bd9Sstevel@tonic-gate 9367c478bd9Sstevel@tonic-gate thread_unlock(t); 9377c478bd9Sstevel@tonic-gate 9387c478bd9Sstevel@tonic-gate if (code != 0 && code < NSYSCALL) { 9397c478bd9Sstevel@tonic-gate nargs = LWP_GETSYSENT(lwp)[code].sy_narg; 9407c478bd9Sstevel@tonic-gate 9417c478bd9Sstevel@tonic-gate ASSERT(nargs <= MAXSYSARGS); 9427c478bd9Sstevel@tonic-gate 9437c478bd9Sstevel@tonic-gate *nargsp = nargs; 9447c478bd9Sstevel@tonic-gate while (nargs-- > 0) 9457c478bd9Sstevel@tonic-gate *argp++ = *ap++ & mask; 9467c478bd9Sstevel@tonic-gate } else { 9477c478bd9Sstevel@tonic-gate *nargsp = 0; 9487c478bd9Sstevel@tonic-gate } 9497c478bd9Sstevel@tonic-gate 9507c478bd9Sstevel@tonic-gate return (code); 9517c478bd9Sstevel@tonic-gate } 9527c478bd9Sstevel@tonic-gate 9537c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 9547c478bd9Sstevel@tonic-gate /* 9557c478bd9Sstevel@tonic-gate * Get the arguments to the current 32-bit system call. 9567c478bd9Sstevel@tonic-gate */ 9577c478bd9Sstevel@tonic-gate uint_t 9587c478bd9Sstevel@tonic-gate get_syscall32_args(klwp_t *lwp, int *argp, int *nargsp) 9597c478bd9Sstevel@tonic-gate { 9607c478bd9Sstevel@tonic-gate long args[MAXSYSARGS]; 9617c478bd9Sstevel@tonic-gate uint_t i, code; 9627c478bd9Sstevel@tonic-gate 9637c478bd9Sstevel@tonic-gate code = get_syscall_args(lwp, args, nargsp); 9647c478bd9Sstevel@tonic-gate 9657c478bd9Sstevel@tonic-gate for (i = 0; i != *nargsp; i++) 9667c478bd9Sstevel@tonic-gate *argp++ = (int)args[i]; 9677c478bd9Sstevel@tonic-gate return (code); 9687c478bd9Sstevel@tonic-gate } 9697c478bd9Sstevel@tonic-gate #endif 9707c478bd9Sstevel@tonic-gate 9717c478bd9Sstevel@tonic-gate /* 9727c478bd9Sstevel@tonic-gate * Save the system call arguments in a safe place. 9737c478bd9Sstevel@tonic-gate * 9747c478bd9Sstevel@tonic-gate * On the i386 kernel: 9757c478bd9Sstevel@tonic-gate * 9767c478bd9Sstevel@tonic-gate * Copy the users args prior to changing the stack or stack pointer. 9777c478bd9Sstevel@tonic-gate * This is so /proc will be able to get a valid copy of the 9787c478bd9Sstevel@tonic-gate * args from the user stack even after the user stack has been changed. 9797c478bd9Sstevel@tonic-gate * Note that the kernel stack copy of the args may also have been 9807c478bd9Sstevel@tonic-gate * changed by a system call handler which takes C-style arguments. 9817c478bd9Sstevel@tonic-gate * 9827c478bd9Sstevel@tonic-gate * Note that this may be called by stop() from trap(). In that case 9837c478bd9Sstevel@tonic-gate * t_sysnum will be zero (syscall_exit clears it), so no args will be 9847c478bd9Sstevel@tonic-gate * copied. 9857c478bd9Sstevel@tonic-gate * 9867c478bd9Sstevel@tonic-gate * On the amd64 kernel: 9877c478bd9Sstevel@tonic-gate * 9887c478bd9Sstevel@tonic-gate * For 64-bit applications, lwp->lwp_ap normally points to %rdi..%r9 9897c478bd9Sstevel@tonic-gate * in the reg structure. If the user is going to change the argument 9907c478bd9Sstevel@tonic-gate * registers, rax, or the stack and might want to get the args (for 9917c478bd9Sstevel@tonic-gate * /proc tracing), it must copy the args elsewhere via save_syscall_args(). 9927c478bd9Sstevel@tonic-gate * 9937c478bd9Sstevel@tonic-gate * For 32-bit applications, lwp->lwp_ap normally points to a copy of 9947c478bd9Sstevel@tonic-gate * the system call arguments on the kernel stack made from the user 9957c478bd9Sstevel@tonic-gate * stack. Copy the args prior to change the stack or stack pointer. 9967c478bd9Sstevel@tonic-gate * This is so /proc will be able to get a valid copy of the args 9977c478bd9Sstevel@tonic-gate * from the user stack even after that stack has been changed. 9987c478bd9Sstevel@tonic-gate * 9997c478bd9Sstevel@tonic-gate * This may be called from stop() even when we're not in a system call. 10007c478bd9Sstevel@tonic-gate * Since there's no easy way to tell, this must be safe (not panic). 10017c478bd9Sstevel@tonic-gate * If the copyins get data faults, return non-zero. 10027c478bd9Sstevel@tonic-gate */ 10037c478bd9Sstevel@tonic-gate int 10047c478bd9Sstevel@tonic-gate save_syscall_args() 10057c478bd9Sstevel@tonic-gate { 10067c478bd9Sstevel@tonic-gate kthread_t *t = curthread; 10077c478bd9Sstevel@tonic-gate klwp_t *lwp = ttolwp(t); 10087c478bd9Sstevel@tonic-gate uint_t code = t->t_sysnum; 10097c478bd9Sstevel@tonic-gate uint_t nargs; 10107c478bd9Sstevel@tonic-gate 10117c478bd9Sstevel@tonic-gate if (lwp->lwp_argsaved || code == 0) 10127c478bd9Sstevel@tonic-gate return (0); /* args already saved or not needed */ 10137c478bd9Sstevel@tonic-gate 10147c478bd9Sstevel@tonic-gate if (code >= NSYSCALL) { 10157c478bd9Sstevel@tonic-gate nargs = 0; /* illegal syscall */ 10167c478bd9Sstevel@tonic-gate } else { 10177c478bd9Sstevel@tonic-gate struct sysent *se = LWP_GETSYSENT(lwp); 10187c478bd9Sstevel@tonic-gate struct sysent *callp = se + code; 10197c478bd9Sstevel@tonic-gate 10207c478bd9Sstevel@tonic-gate nargs = callp->sy_narg; 10217c478bd9Sstevel@tonic-gate if (LOADABLE_SYSCALL(callp) && nargs == 0) { 10227c478bd9Sstevel@tonic-gate krwlock_t *module_lock; 10237c478bd9Sstevel@tonic-gate 10247c478bd9Sstevel@tonic-gate /* 10257c478bd9Sstevel@tonic-gate * Find out how many arguments the system 10267c478bd9Sstevel@tonic-gate * call uses. 10277c478bd9Sstevel@tonic-gate * 10287c478bd9Sstevel@tonic-gate * We have the property that loaded syscalls 10297c478bd9Sstevel@tonic-gate * never change the number of arguments they 10307c478bd9Sstevel@tonic-gate * use after they've been loaded once. This 10317c478bd9Sstevel@tonic-gate * allows us to stop for /proc tracing without 10327c478bd9Sstevel@tonic-gate * holding the module lock. 10337c478bd9Sstevel@tonic-gate * /proc is assured that sy_narg is valid. 10347c478bd9Sstevel@tonic-gate */ 10357c478bd9Sstevel@tonic-gate module_lock = lock_syscall(se, code); 10367c478bd9Sstevel@tonic-gate nargs = callp->sy_narg; 10377c478bd9Sstevel@tonic-gate rw_exit(module_lock); 10387c478bd9Sstevel@tonic-gate } 10397c478bd9Sstevel@tonic-gate } 10407c478bd9Sstevel@tonic-gate 10417c478bd9Sstevel@tonic-gate /* 10427c478bd9Sstevel@tonic-gate * Fetch the system call arguments. 10437c478bd9Sstevel@tonic-gate */ 10447c478bd9Sstevel@tonic-gate if (nargs == 0) 10457c478bd9Sstevel@tonic-gate goto out; 10467c478bd9Sstevel@tonic-gate 10477c478bd9Sstevel@tonic-gate ASSERT(nargs <= MAXSYSARGS); 10487c478bd9Sstevel@tonic-gate 10497c478bd9Sstevel@tonic-gate if (lwp_getdatamodel(lwp) == DATAMODEL_NATIVE) { 10507c478bd9Sstevel@tonic-gate #if defined(_LP64) 10517c478bd9Sstevel@tonic-gate struct regs *rp = lwptoregs(lwp); 10527c478bd9Sstevel@tonic-gate 10537c478bd9Sstevel@tonic-gate lwp->lwp_arg[0] = rp->r_rdi; 10547c478bd9Sstevel@tonic-gate lwp->lwp_arg[1] = rp->r_rsi; 10557c478bd9Sstevel@tonic-gate lwp->lwp_arg[2] = rp->r_rdx; 10567c478bd9Sstevel@tonic-gate lwp->lwp_arg[3] = rp->r_rcx; 10577c478bd9Sstevel@tonic-gate lwp->lwp_arg[4] = rp->r_r8; 10587c478bd9Sstevel@tonic-gate lwp->lwp_arg[5] = rp->r_r9; 10597c478bd9Sstevel@tonic-gate if (nargs > 6 && copyin_args(rp, &lwp->lwp_arg[6], nargs - 6)) 10607c478bd9Sstevel@tonic-gate return (-1); 10617c478bd9Sstevel@tonic-gate } else { 10627c478bd9Sstevel@tonic-gate #endif 10637c478bd9Sstevel@tonic-gate if (COPYIN_ARGS32(lwptoregs(lwp), lwp->lwp_arg, nargs)) 10647c478bd9Sstevel@tonic-gate return (-1); 10657c478bd9Sstevel@tonic-gate } 10667c478bd9Sstevel@tonic-gate out: 10677c478bd9Sstevel@tonic-gate lwp->lwp_ap = lwp->lwp_arg; 10687c478bd9Sstevel@tonic-gate lwp->lwp_argsaved = 1; 10697c478bd9Sstevel@tonic-gate t->t_post_sys = 1; /* so lwp_ap will be reset */ 10707c478bd9Sstevel@tonic-gate return (0); 10717c478bd9Sstevel@tonic-gate } 10727c478bd9Sstevel@tonic-gate 10737c478bd9Sstevel@tonic-gate void 10747c478bd9Sstevel@tonic-gate reset_syscall_args(void) 10757c478bd9Sstevel@tonic-gate { 10767c478bd9Sstevel@tonic-gate ttolwp(curthread)->lwp_argsaved = 0; 10777c478bd9Sstevel@tonic-gate } 10787c478bd9Sstevel@tonic-gate 10797c478bd9Sstevel@tonic-gate /* 10807c478bd9Sstevel@tonic-gate * Call a system call which takes a pointer to the user args struct and 10817c478bd9Sstevel@tonic-gate * a pointer to the return values. This is a bit slower than the standard 10827c478bd9Sstevel@tonic-gate * C arg-passing method in some cases. 10837c478bd9Sstevel@tonic-gate */ 10847c478bd9Sstevel@tonic-gate int64_t 10857c478bd9Sstevel@tonic-gate syscall_ap(void) 10867c478bd9Sstevel@tonic-gate { 10877c478bd9Sstevel@tonic-gate uint_t error; 10887c478bd9Sstevel@tonic-gate struct sysent *callp; 10897c478bd9Sstevel@tonic-gate rval_t rval; 10907c478bd9Sstevel@tonic-gate kthread_t *t = curthread; 10917c478bd9Sstevel@tonic-gate klwp_t *lwp = ttolwp(t); 10927c478bd9Sstevel@tonic-gate struct regs *rp = lwptoregs(lwp); 10937c478bd9Sstevel@tonic-gate 10947c478bd9Sstevel@tonic-gate callp = LWP_GETSYSENT(lwp) + t->t_sysnum; 10957c478bd9Sstevel@tonic-gate 10967c478bd9Sstevel@tonic-gate #if defined(__amd64) 10977c478bd9Sstevel@tonic-gate /* 10987c478bd9Sstevel@tonic-gate * If the arguments don't fit in registers %rdi-%r9, make sure they 10997c478bd9Sstevel@tonic-gate * have been copied to the lwp_arg array. 11007c478bd9Sstevel@tonic-gate */ 11017c478bd9Sstevel@tonic-gate if (callp->sy_narg > 6 && save_syscall_args()) 11027c478bd9Sstevel@tonic-gate return ((int64_t)set_errno(EFAULT)); 11037c478bd9Sstevel@tonic-gate #endif 11047c478bd9Sstevel@tonic-gate 11057c478bd9Sstevel@tonic-gate rval.r_val1 = 0; 11067c478bd9Sstevel@tonic-gate rval.r_val2 = rp->r_r1; 11077c478bd9Sstevel@tonic-gate lwp->lwp_error = 0; /* for old drivers */ 11087c478bd9Sstevel@tonic-gate error = (*(callp->sy_call))(lwp->lwp_ap, &rval); 11097c478bd9Sstevel@tonic-gate if (error) 11107c478bd9Sstevel@tonic-gate return ((longlong_t)set_errno(error)); 11117c478bd9Sstevel@tonic-gate return (rval.r_vals); 11127c478bd9Sstevel@tonic-gate } 11137c478bd9Sstevel@tonic-gate 11147c478bd9Sstevel@tonic-gate /* 11157c478bd9Sstevel@tonic-gate * Load system call module. 11167c478bd9Sstevel@tonic-gate * Returns with pointer to held read lock for module. 11177c478bd9Sstevel@tonic-gate */ 11187c478bd9Sstevel@tonic-gate static krwlock_t * 11197c478bd9Sstevel@tonic-gate lock_syscall(struct sysent *table, uint_t code) 11207c478bd9Sstevel@tonic-gate { 11217c478bd9Sstevel@tonic-gate krwlock_t *module_lock; 11227c478bd9Sstevel@tonic-gate struct modctl *modp; 11237c478bd9Sstevel@tonic-gate int id; 11247c478bd9Sstevel@tonic-gate struct sysent *callp; 11257c478bd9Sstevel@tonic-gate 11267c478bd9Sstevel@tonic-gate callp = table + code; 11277c478bd9Sstevel@tonic-gate module_lock = callp->sy_lock; 11287c478bd9Sstevel@tonic-gate 11297c478bd9Sstevel@tonic-gate /* 11307c478bd9Sstevel@tonic-gate * Optimization to only call modload if we don't have a loaded 11317c478bd9Sstevel@tonic-gate * syscall. 11327c478bd9Sstevel@tonic-gate */ 11337c478bd9Sstevel@tonic-gate rw_enter(module_lock, RW_READER); 11347c478bd9Sstevel@tonic-gate if (LOADED_SYSCALL(callp)) 11357c478bd9Sstevel@tonic-gate return (module_lock); 11367c478bd9Sstevel@tonic-gate rw_exit(module_lock); 11377c478bd9Sstevel@tonic-gate 11387c478bd9Sstevel@tonic-gate for (;;) { 11397c478bd9Sstevel@tonic-gate if ((id = modload("sys", syscallnames[code])) == -1) 11407c478bd9Sstevel@tonic-gate break; 11417c478bd9Sstevel@tonic-gate 11427c478bd9Sstevel@tonic-gate /* 11437c478bd9Sstevel@tonic-gate * If we loaded successfully at least once, the modctl 11447c478bd9Sstevel@tonic-gate * will still be valid, so we try to grab it by filename. 11457c478bd9Sstevel@tonic-gate * If this call fails, it's because the mod_filename 11467c478bd9Sstevel@tonic-gate * was changed after the call to modload() (mod_hold_by_name() 11477c478bd9Sstevel@tonic-gate * is the likely culprit). We can safely just take 11487c478bd9Sstevel@tonic-gate * another lap if this is the case; the modload() will 11497c478bd9Sstevel@tonic-gate * change the mod_filename back to one by which we can 11507c478bd9Sstevel@tonic-gate * find the modctl. 11517c478bd9Sstevel@tonic-gate */ 11527c478bd9Sstevel@tonic-gate modp = mod_find_by_filename("sys", syscallnames[code]); 11537c478bd9Sstevel@tonic-gate 11547c478bd9Sstevel@tonic-gate if (modp == NULL) 11557c478bd9Sstevel@tonic-gate continue; 11567c478bd9Sstevel@tonic-gate 11577c478bd9Sstevel@tonic-gate mutex_enter(&mod_lock); 11587c478bd9Sstevel@tonic-gate 11597c478bd9Sstevel@tonic-gate if (!modp->mod_installed) { 11607c478bd9Sstevel@tonic-gate mutex_exit(&mod_lock); 11617c478bd9Sstevel@tonic-gate continue; 11627c478bd9Sstevel@tonic-gate } 11637c478bd9Sstevel@tonic-gate break; 11647c478bd9Sstevel@tonic-gate } 11657c478bd9Sstevel@tonic-gate rw_enter(module_lock, RW_READER); 11667c478bd9Sstevel@tonic-gate 11677c478bd9Sstevel@tonic-gate if (id != -1) 11687c478bd9Sstevel@tonic-gate mutex_exit(&mod_lock); 11697c478bd9Sstevel@tonic-gate 11707c478bd9Sstevel@tonic-gate return (module_lock); 11717c478bd9Sstevel@tonic-gate } 11727c478bd9Sstevel@tonic-gate 11737c478bd9Sstevel@tonic-gate /* 11747c478bd9Sstevel@tonic-gate * Loadable syscall support. 11757c478bd9Sstevel@tonic-gate * If needed, load the module, then reserve it by holding a read 11767c478bd9Sstevel@tonic-gate * lock for the duration of the call. 11777c478bd9Sstevel@tonic-gate * Later, if the syscall is not unloadable, it could patch the vector. 11787c478bd9Sstevel@tonic-gate */ 11797c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 11807c478bd9Sstevel@tonic-gate int64_t 11817c478bd9Sstevel@tonic-gate loadable_syscall( 11827c478bd9Sstevel@tonic-gate long a0, long a1, long a2, long a3, 11837c478bd9Sstevel@tonic-gate long a4, long a5, long a6, long a7) 11847c478bd9Sstevel@tonic-gate { 11857c478bd9Sstevel@tonic-gate klwp_t *lwp = ttolwp(curthread); 11867c478bd9Sstevel@tonic-gate int64_t rval; 11877c478bd9Sstevel@tonic-gate struct sysent *callp; 11887c478bd9Sstevel@tonic-gate struct sysent *se = LWP_GETSYSENT(lwp); 11897c478bd9Sstevel@tonic-gate krwlock_t *module_lock; 11907c478bd9Sstevel@tonic-gate int code, error = 0; 11917c478bd9Sstevel@tonic-gate int64_t (*sy_call)(); 11927c478bd9Sstevel@tonic-gate 11937c478bd9Sstevel@tonic-gate code = curthread->t_sysnum; 11947c478bd9Sstevel@tonic-gate callp = se + code; 11957c478bd9Sstevel@tonic-gate 11967c478bd9Sstevel@tonic-gate /* 11977c478bd9Sstevel@tonic-gate * Try to autoload the system call if necessary 11987c478bd9Sstevel@tonic-gate */ 11997c478bd9Sstevel@tonic-gate module_lock = lock_syscall(se, code); 12007c478bd9Sstevel@tonic-gate 12017c478bd9Sstevel@tonic-gate /* 12027c478bd9Sstevel@tonic-gate * we've locked either the loaded syscall or nosys 12037c478bd9Sstevel@tonic-gate */ 12047c478bd9Sstevel@tonic-gate 12057c478bd9Sstevel@tonic-gate if (lwp_getdatamodel(lwp) == DATAMODEL_NATIVE) { 12067c478bd9Sstevel@tonic-gate #if defined(_LP64) 12077c478bd9Sstevel@tonic-gate if (callp->sy_flags & SE_ARGC) { 12087c478bd9Sstevel@tonic-gate sy_call = (int64_t (*)())callp->sy_call; 12097c478bd9Sstevel@tonic-gate rval = (*sy_call)(a0, a1, a2, a3, a4, a5); 12107c478bd9Sstevel@tonic-gate } else 12117c478bd9Sstevel@tonic-gate rval = syscall_ap(); 12127c478bd9Sstevel@tonic-gate } else { 12137c478bd9Sstevel@tonic-gate #endif 12147c478bd9Sstevel@tonic-gate /* 12157c478bd9Sstevel@tonic-gate * Now that it's loaded, make sure enough args were copied. 12167c478bd9Sstevel@tonic-gate */ 12177c478bd9Sstevel@tonic-gate if (COPYIN_ARGS32(lwptoregs(lwp), lwp->lwp_ap, callp->sy_narg)) 12187c478bd9Sstevel@tonic-gate error = EFAULT; 12197c478bd9Sstevel@tonic-gate if (error) { 12207c478bd9Sstevel@tonic-gate rval = set_errno(error); 12217c478bd9Sstevel@tonic-gate } else if (callp->sy_flags & SE_ARGC) { 12227c478bd9Sstevel@tonic-gate sy_call = (int64_t (*)())callp->sy_call; 12237c478bd9Sstevel@tonic-gate rval = (*sy_call)(lwp->lwp_ap[0], lwp->lwp_ap[1], 12247c478bd9Sstevel@tonic-gate lwp->lwp_ap[2], lwp->lwp_ap[3], lwp->lwp_ap[4], 12257c478bd9Sstevel@tonic-gate lwp->lwp_ap[5]); 12267c478bd9Sstevel@tonic-gate } else 12277c478bd9Sstevel@tonic-gate rval = syscall_ap(); 12287c478bd9Sstevel@tonic-gate } 12297c478bd9Sstevel@tonic-gate 12307c478bd9Sstevel@tonic-gate rw_exit(module_lock); 12317c478bd9Sstevel@tonic-gate return (rval); 12327c478bd9Sstevel@tonic-gate } 12337c478bd9Sstevel@tonic-gate 12347c478bd9Sstevel@tonic-gate /* 12357c478bd9Sstevel@tonic-gate * Indirect syscall handled in libc on x86 architectures 12367c478bd9Sstevel@tonic-gate */ 12377c478bd9Sstevel@tonic-gate int64_t 12387c478bd9Sstevel@tonic-gate indir() 12397c478bd9Sstevel@tonic-gate { 12407c478bd9Sstevel@tonic-gate return (nosys()); 12417c478bd9Sstevel@tonic-gate } 12427c478bd9Sstevel@tonic-gate 12437c478bd9Sstevel@tonic-gate /* 12447c478bd9Sstevel@tonic-gate * set_errno - set an error return from the current system call. 12457c478bd9Sstevel@tonic-gate * This could be a macro. 12467c478bd9Sstevel@tonic-gate * This returns the value it is passed, so that the caller can 12477c478bd9Sstevel@tonic-gate * use tail-recursion-elimination and do return (set_errno(ERRNO)); 12487c478bd9Sstevel@tonic-gate */ 12497c478bd9Sstevel@tonic-gate uint_t 12507c478bd9Sstevel@tonic-gate set_errno(uint_t error) 12517c478bd9Sstevel@tonic-gate { 12527c478bd9Sstevel@tonic-gate ASSERT(error != 0); /* must not be used to clear errno */ 12537c478bd9Sstevel@tonic-gate 12547c478bd9Sstevel@tonic-gate curthread->t_post_sys = 1; /* have post_syscall do error return */ 12557c478bd9Sstevel@tonic-gate return (ttolwp(curthread)->lwp_errno = error); 12567c478bd9Sstevel@tonic-gate } 12577c478bd9Sstevel@tonic-gate 12587c478bd9Sstevel@tonic-gate /* 12597c478bd9Sstevel@tonic-gate * set_proc_pre_sys - Set pre-syscall processing for entire process. 12607c478bd9Sstevel@tonic-gate */ 12617c478bd9Sstevel@tonic-gate void 12627c478bd9Sstevel@tonic-gate set_proc_pre_sys(proc_t *p) 12637c478bd9Sstevel@tonic-gate { 12647c478bd9Sstevel@tonic-gate kthread_t *t; 12657c478bd9Sstevel@tonic-gate kthread_t *first; 12667c478bd9Sstevel@tonic-gate 12677c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock)); 12687c478bd9Sstevel@tonic-gate 12697c478bd9Sstevel@tonic-gate t = first = p->p_tlist; 12707c478bd9Sstevel@tonic-gate do { 12717c478bd9Sstevel@tonic-gate t->t_pre_sys = 1; 12727c478bd9Sstevel@tonic-gate } while ((t = t->t_forw) != first); 12737c478bd9Sstevel@tonic-gate } 12747c478bd9Sstevel@tonic-gate 12757c478bd9Sstevel@tonic-gate /* 12767c478bd9Sstevel@tonic-gate * set_proc_post_sys - Set post-syscall processing for entire process. 12777c478bd9Sstevel@tonic-gate */ 12787c478bd9Sstevel@tonic-gate void 12797c478bd9Sstevel@tonic-gate set_proc_post_sys(proc_t *p) 12807c478bd9Sstevel@tonic-gate { 12817c478bd9Sstevel@tonic-gate kthread_t *t; 12827c478bd9Sstevel@tonic-gate kthread_t *first; 12837c478bd9Sstevel@tonic-gate 12847c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock)); 12857c478bd9Sstevel@tonic-gate 12867c478bd9Sstevel@tonic-gate t = first = p->p_tlist; 12877c478bd9Sstevel@tonic-gate do { 12887c478bd9Sstevel@tonic-gate t->t_post_sys = 1; 12897c478bd9Sstevel@tonic-gate } while ((t = t->t_forw) != first); 12907c478bd9Sstevel@tonic-gate } 12917c478bd9Sstevel@tonic-gate 12927c478bd9Sstevel@tonic-gate /* 12937c478bd9Sstevel@tonic-gate * set_proc_sys - Set pre- and post-syscall processing for entire process. 12947c478bd9Sstevel@tonic-gate */ 12957c478bd9Sstevel@tonic-gate void 12967c478bd9Sstevel@tonic-gate set_proc_sys(proc_t *p) 12977c478bd9Sstevel@tonic-gate { 12987c478bd9Sstevel@tonic-gate kthread_t *t; 12997c478bd9Sstevel@tonic-gate kthread_t *first; 13007c478bd9Sstevel@tonic-gate 13017c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock)); 13027c478bd9Sstevel@tonic-gate 13037c478bd9Sstevel@tonic-gate t = first = p->p_tlist; 13047c478bd9Sstevel@tonic-gate do { 13057c478bd9Sstevel@tonic-gate t->t_pre_sys = 1; 13067c478bd9Sstevel@tonic-gate t->t_post_sys = 1; 13077c478bd9Sstevel@tonic-gate } while ((t = t->t_forw) != first); 13087c478bd9Sstevel@tonic-gate } 13097c478bd9Sstevel@tonic-gate 13107c478bd9Sstevel@tonic-gate /* 13117c478bd9Sstevel@tonic-gate * set_all_proc_sys - set pre- and post-syscall processing flags for all 13127c478bd9Sstevel@tonic-gate * user processes. 13137c478bd9Sstevel@tonic-gate * 13147c478bd9Sstevel@tonic-gate * This is needed when auditing, tracing, or other facilities which affect 13157c478bd9Sstevel@tonic-gate * all processes are turned on. 13167c478bd9Sstevel@tonic-gate */ 13177c478bd9Sstevel@tonic-gate void 13187c478bd9Sstevel@tonic-gate set_all_proc_sys() 13197c478bd9Sstevel@tonic-gate { 13207c478bd9Sstevel@tonic-gate kthread_t *t; 13217c478bd9Sstevel@tonic-gate kthread_t *first; 13227c478bd9Sstevel@tonic-gate 13237c478bd9Sstevel@tonic-gate mutex_enter(&pidlock); 13247c478bd9Sstevel@tonic-gate t = first = curthread; 13257c478bd9Sstevel@tonic-gate do { 13267c478bd9Sstevel@tonic-gate t->t_pre_sys = 1; 13277c478bd9Sstevel@tonic-gate t->t_post_sys = 1; 13287c478bd9Sstevel@tonic-gate } while ((t = t->t_next) != first); 13297c478bd9Sstevel@tonic-gate mutex_exit(&pidlock); 13307c478bd9Sstevel@tonic-gate } 13317c478bd9Sstevel@tonic-gate 13327c478bd9Sstevel@tonic-gate /* 1333005d3febSMarek Pospisil * set_all_zone_usr_proc_sys - set pre- and post-syscall processing flags for 1334005d3febSMarek Pospisil * all user processes running in the zone of the current process 1335005d3febSMarek Pospisil * 1336005d3febSMarek Pospisil * This is needed when auditing, tracing, or other facilities which affect 1337005d3febSMarek Pospisil * all processes are turned on. 1338005d3febSMarek Pospisil */ 1339005d3febSMarek Pospisil void 1340005d3febSMarek Pospisil set_all_zone_usr_proc_sys(zoneid_t zoneid) 1341005d3febSMarek Pospisil { 1342005d3febSMarek Pospisil proc_t *p; 1343005d3febSMarek Pospisil kthread_t *t; 1344005d3febSMarek Pospisil 1345005d3febSMarek Pospisil mutex_enter(&pidlock); 1346005d3febSMarek Pospisil for (p = practive; p != NULL; p = p->p_next) { 1347005d3febSMarek Pospisil /* skip kernel and incomplete processes */ 1348005d3febSMarek Pospisil if (p->p_exec == NULLVP || p->p_as == &kas || 1349005d3febSMarek Pospisil p->p_stat == SIDL || p->p_stat == SZOMB || 1350005d3febSMarek Pospisil (p->p_flag & (SSYS | SEXITING | SEXITLWPS))) 1351005d3febSMarek Pospisil continue; 1352005d3febSMarek Pospisil /* 1353005d3febSMarek Pospisil * Only processes in the given zone (eventually in 1354005d3febSMarek Pospisil * all zones) are taken into account 1355005d3febSMarek Pospisil */ 1356005d3febSMarek Pospisil if (zoneid == ALL_ZONES || p->p_zone->zone_id == zoneid) { 1357005d3febSMarek Pospisil mutex_enter(&p->p_lock); 135896992ee7SEthindra Ramamurthy if ((t = p->p_tlist) == NULL) { 135996992ee7SEthindra Ramamurthy mutex_exit(&p->p_lock); 1360005d3febSMarek Pospisil continue; 136196992ee7SEthindra Ramamurthy } 1362005d3febSMarek Pospisil /* 1363005d3febSMarek Pospisil * Set pre- and post-syscall processing flags 1364005d3febSMarek Pospisil * for all threads of the process 1365005d3febSMarek Pospisil */ 1366005d3febSMarek Pospisil do { 1367005d3febSMarek Pospisil t->t_pre_sys = 1; 1368005d3febSMarek Pospisil t->t_post_sys = 1; 1369005d3febSMarek Pospisil } while (p->p_tlist != (t = t->t_forw)); 1370005d3febSMarek Pospisil mutex_exit(&p->p_lock); 1371005d3febSMarek Pospisil } 1372005d3febSMarek Pospisil } 1373005d3febSMarek Pospisil mutex_exit(&pidlock); 1374005d3febSMarek Pospisil } 1375005d3febSMarek Pospisil 1376005d3febSMarek Pospisil /* 13777c478bd9Sstevel@tonic-gate * set_proc_ast - Set asynchronous service trap (AST) flag for all 13787c478bd9Sstevel@tonic-gate * threads in process. 13797c478bd9Sstevel@tonic-gate */ 13807c478bd9Sstevel@tonic-gate void 13817c478bd9Sstevel@tonic-gate set_proc_ast(proc_t *p) 13827c478bd9Sstevel@tonic-gate { 13837c478bd9Sstevel@tonic-gate kthread_t *t; 13847c478bd9Sstevel@tonic-gate kthread_t *first; 13857c478bd9Sstevel@tonic-gate 13867c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock)); 13877c478bd9Sstevel@tonic-gate 13887c478bd9Sstevel@tonic-gate t = first = p->p_tlist; 13897c478bd9Sstevel@tonic-gate do { 13907c478bd9Sstevel@tonic-gate aston(t); 13917c478bd9Sstevel@tonic-gate } while ((t = t->t_forw) != first); 13927c478bd9Sstevel@tonic-gate } 1393