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