subr_syscall.c revision 93793
11927Swollman/*- 21927Swollman * Copyright (C) 1994, David Greenman 31927Swollman * Copyright (c) 1990, 1993 41927Swollman * The Regents of the University of California. All rights reserved. 51927Swollman * 61927Swollman * This code is derived from software contributed to Berkeley by 71927Swollman * the University of Utah, and William Jolitz. 81927Swollman * 91927Swollman * Redistribution and use in source and binary forms, with or without 101927Swollman * modification, are permitted provided that the following conditions 111927Swollman * are met: 121927Swollman * 1. Redistributions of source code must retain the above copyright 131927Swollman * notice, this list of conditions and the following disclaimer. 141927Swollman * 2. Redistributions in binary form must reproduce the above copyright 151927Swollman * notice, this list of conditions and the following disclaimer in the 161927Swollman * documentation and/or other materials provided with the distribution. 171927Swollman * 3. All advertising materials mentioning features or use of this software 181927Swollman * must display the following acknowledgement: 191927Swollman * This product includes software developed by the University of 201927Swollman * California, Berkeley and its contributors. 211927Swollman * 4. Neither the name of the University nor the names of its contributors 221927Swollman * may be used to endorse or promote products derived from this software 231927Swollman * without specific prior written permission. 241927Swollman * 251927Swollman * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 261927Swollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 271927Swollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 281927Swollman * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 291927Swollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 301927Swollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 311927Swollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 321927Swollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 331927Swollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 341927Swollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 351927Swollman * SUCH DAMAGE. 361927Swollman * 371927Swollman * from: @(#)trap.c 7.4 (Berkeley) 5/13/91 381927Swollman * $FreeBSD: head/sys/kern/subr_trap.c 93793 2002-04-04 17:49:48Z bde $ 391927Swollman */ 401927Swollman 411927Swollman#ifdef __i386__ 421927Swollman#include "opt_npx.h" 431927Swollman#endif 441927Swollman 451927Swollman#include <sys/param.h> 461927Swollman#include <sys/bus.h> 471927Swollman#include <sys/kernel.h> 481927Swollman#include <sys/lock.h> 491927Swollman#include <sys/mutex.h> 501927Swollman#include <sys/proc.h> 511927Swollman#include <sys/resourcevar.h> 521927Swollman#include <sys/signalvar.h> 531927Swollman#include <sys/systm.h> 541927Swollman#include <sys/vmmeter.h> 551927Swollman#include <machine/cpu.h> 561927Swollman#include <machine/pcb.h> 571927Swollman 581927Swollman/* 591927Swollman * Define the code needed before returning to user mode, for 601927Swollman * trap and syscall. 611927Swollman * 621927Swollman * MPSAFE 631927Swollman */ 641927Swollmanvoid 651927Swollmanuserret(td, frame, oticks) 661927Swollman struct thread *td; 671927Swollman struct trapframe *frame; 681927Swollman u_int oticks; 691927Swollman{ 701927Swollman struct proc *p = td->td_proc; 711927Swollman struct kse *ke = td->td_kse; 721927Swollman struct ksegrp *kg = td->td_ksegrp; 731927Swollman 741927Swollman#ifdef INVARIANTS 751927Swollman /* Check that we called signotify() enough. */ 761927Swollman mtx_lock(&Giant); 771927Swollman PROC_LOCK(p); 781927Swollman mtx_lock_spin(&sched_lock); 791927Swollman if (SIGPENDING(p) && ((p->p_sflag & PS_NEEDSIGCHK) == 0 || 801927Swollman (p->p_kse.ke_flags & KEF_ASTPENDING) == 0)) 811927Swollman printf("failed to set signal flags proprly for ast()\n"); 821927Swollman mtx_unlock_spin(&sched_lock); 831927Swollman PROC_UNLOCK(p); 841927Swollman mtx_unlock(&Giant); 851927Swollman#endif 861927Swollman 871927Swollman /* 881927Swollman * XXX we cheat slightly on the locking here to avoid locking in 891927Swollman * the usual case. Setting td_priority here is essentially an 901927Swollman * incomplete workaround for not setting it properly elsewhere. 911927Swollman * Now that some interrupt handlers are threads, not setting it 921927Swollman * properly elsewhere can clobber it in the window between setting 931927Swollman * it here and returning to user mode, so don't waste time setting 941927Swollman * it perfectly here. 951927Swollman */ 961927Swollman if (td->td_priority != kg->kg_user_pri) { 971927Swollman mtx_lock_spin(&sched_lock); 981927Swollman td->td_priority = kg->kg_user_pri; 991927Swollman mtx_unlock_spin(&sched_lock); 1001927Swollman } 1011927Swollman 1021927Swollman /* 1031927Swollman * Charge system time if profiling. 1041927Swollman * 1051927Swollman * XXX should move PS_PROFIL to a place that can obviously be 1061927Swollman * accessed safely without sched_lock. 1071927Swollman */ 1081927Swollman if (p->p_sflag & PS_PROFIL) { 1091927Swollman quad_t ticks; 1101927Swollman 1111927Swollman mtx_lock_spin(&sched_lock); 1121927Swollman ticks = ke->ke_sticks - oticks; 1131927Swollman mtx_unlock_spin(&sched_lock); 1141927Swollman addupc_task(ke, TRAPF_PC(frame), (u_int)ticks * psratio); 1151927Swollman } 1161927Swollman} 1171927Swollman 1181927Swollman/* 1191927Swollman * Process an asynchronous software trap. 1201927Swollman * This is relatively easy. 1211927Swollman * This function will return with preemption disabled. 1221927Swollman */ 1231927Swollmanvoid 1241927Swollmanast(framep) 1251927Swollman struct trapframe *framep; 1261927Swollman{ 1271927Swollman struct thread *td = curthread; 1281927Swollman struct proc *p = td->td_proc; 1291927Swollman struct kse *ke = td->td_kse; 1301927Swollman struct ksegrp *kg = td->td_ksegrp; 1311927Swollman u_int prticks, sticks; 1321927Swollman int sflag; 1331927Swollman int flags; 1341927Swollman int sig; 1351927Swollman#if defined(DEV_NPX) && !defined(SMP) 1361927Swollman int ucode; 1371927Swollman#endif 1381927Swollman 1391927Swollman KASSERT(TRAPF_USERMODE(framep), ("ast in kernel mode")); 1401927Swollman#ifdef WITNESS 1411927Swollman if (witness_list(td)) 1421927Swollman panic("Returning to user mode with mutex(s) held"); 1431927Swollman#endif 1441927Swollman mtx_assert(&Giant, MA_NOTOWNED); 1451927Swollman mtx_assert(&sched_lock, MA_NOTOWNED); 1461927Swollman prticks = 0; /* XXX: Quiet warning. */ 1471927Swollman td->td_frame = framep; 1481927Swollman /* 1491927Swollman * This updates the p_sflag's for the checks below in one 1501927Swollman * "atomic" operation with turning off the astpending flag. 1511927Swollman * If another AST is triggered while we are handling the 1521927Swollman * AST's saved in sflag, the astpending flag will be set and 1531927Swollman * ast() will be called again. 1541927Swollman */ 1551927Swollman mtx_lock_spin(&sched_lock); 1561927Swollman sticks = ke->ke_sticks; 1571927Swollman sflag = p->p_sflag; 1581927Swollman flags = ke->ke_flags; 1591927Swollman p->p_sflag &= ~(PS_ALRMPEND | PS_NEEDSIGCHK | PS_PROFPEND); 1601927Swollman ke->ke_flags &= ~(KEF_ASTPENDING | KEF_NEEDRESCHED | KEF_OWEUPC); 1611927Swollman cnt.v_soft++; 1621927Swollman if (flags & KEF_OWEUPC && sflag & PS_PROFIL) { 1631927Swollman prticks = p->p_stats->p_prof.pr_ticks; 1641927Swollman p->p_stats->p_prof.pr_ticks = 0; 1651927Swollman } 1661927Swollman mtx_unlock_spin(&sched_lock); 1671927Swollman 1681927Swollman if (td->td_ucred != p->p_ucred) 1691927Swollman cred_update_thread(td); 1701927Swollman if (flags & KEF_OWEUPC && sflag & PS_PROFIL) 1711927Swollman addupc_task(ke, p->p_stats->p_prof.pr_addr, prticks); 1721927Swollman if (sflag & PS_ALRMPEND) { 1731927Swollman PROC_LOCK(p); 1741927Swollman psignal(p, SIGVTALRM); 1751927Swollman PROC_UNLOCK(p); 1761927Swollman } 1771927Swollman#if defined(DEV_NPX) && !defined(SMP) 1781927Swollman if (PCPU_GET(curpcb)->pcb_flags & PCB_NPXTRAP) { 1791927Swollman atomic_clear_int(&PCPU_GET(curpcb)->pcb_flags, 1801927Swollman PCB_NPXTRAP); 1811927Swollman ucode = npxtrap(); 1821927Swollman if (ucode != -1) { 1831927Swollman trapsignal(p, SIGFPE, ucode); 1841927Swollman } 1851927Swollman } 1861927Swollman#endif 1871927Swollman if (sflag & PS_PROFPEND) { 1881927Swollman PROC_LOCK(p); 1891927Swollman psignal(p, SIGPROF); 1901927Swollman PROC_UNLOCK(p); 1911927Swollman } 1921927Swollman if (flags & KEF_NEEDRESCHED) { 1931927Swollman mtx_lock_spin(&sched_lock); 1941927Swollman td->td_priority = kg->kg_user_pri; 1951927Swollman setrunqueue(td); 1961927Swollman p->p_stats->p_ru.ru_nivcsw++; 1971927Swollman mi_switch(); 1981927Swollman mtx_unlock_spin(&sched_lock); 1991927Swollman } 2001927Swollman if (sflag & PS_NEEDSIGCHK) { 2011927Swollman mtx_lock(&Giant); 2021927Swollman PROC_LOCK(p); 2031927Swollman while ((sig = CURSIG(p)) != 0) 2041927Swollman postsig(sig); 2051927Swollman PROC_UNLOCK(p); 2061927Swollman mtx_unlock(&Giant); 2071927Swollman } 2081927Swollman 2091927Swollman userret(td, framep, sticks); 2101927Swollman#ifdef DIAGNOSTIC 2111927Swollman cred_free_thread(td); 2121927Swollman#endif 2131927Swollman mtx_assert(&Giant, MA_NOTOWNED); 2141927Swollman} 2151927Swollman