subr_syscall.c revision 111032
1228753Smm/*-
2228753Smm * Copyright (C) 1994, David Greenman
3228753Smm * Copyright (c) 1990, 1993
4228753Smm *	The Regents of the University of California.  All rights reserved.
5228753Smm *
6228753Smm * This code is derived from software contributed to Berkeley by
7228753Smm * the University of Utah, and William Jolitz.
8228753Smm *
9228753Smm * Redistribution and use in source and binary forms, with or without
10228753Smm * modification, are permitted provided that the following conditions
11228753Smm * are met:
12228753Smm * 1. Redistributions of source code must retain the above copyright
13228753Smm *    notice, this list of conditions and the following disclaimer.
14228753Smm * 2. Redistributions in binary form must reproduce the above copyright
15228753Smm *    notice, this list of conditions and the following disclaimer in the
16228753Smm *    documentation and/or other materials provided with the distribution.
17228753Smm * 3. All advertising materials mentioning features or use of this software
18228753Smm *    must display the following acknowledgement:
19228753Smm *	This product includes software developed by the University of
20228753Smm *	California, Berkeley and its contributors.
21228753Smm * 4. Neither the name of the University nor the names of its contributors
22228753Smm *    may be used to endorse or promote products derived from this software
23228753Smm *    without specific prior written permission.
24228753Smm *
25228753Smm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26228753Smm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27228753Smm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28231200Smm * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29228753Smm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30228753Smm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31228753Smm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32228753Smm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33228753Smm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34228753Smm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35228753Smm * SUCH DAMAGE.
36228753Smm *
37228753Smm *	from: @(#)trap.c	7.4 (Berkeley) 5/13/91
38228753Smm * $FreeBSD: head/sys/kern/subr_trap.c 111032 2003-02-17 09:55:10Z julian $
39228753Smm */
40228753Smm
41228753Smm#include "opt_mac.h"
42228753Smm#ifdef __i386__
43228753Smm#include "opt_npx.h"
44228753Smm#endif
45228753Smm
46228753Smm#include <sys/param.h>
47228753Smm#include <sys/bus.h>
48228753Smm#include <sys/kernel.h>
49228753Smm#include <sys/lock.h>
50228753Smm#include <sys/mac.h>
51228753Smm#include <sys/mutex.h>
52228753Smm#include <sys/proc.h>
53228753Smm#include <sys/kse.h>
54228753Smm#include <sys/ktr.h>
55228753Smm#include <sys/resourcevar.h>
56228753Smm#include <sys/sched.h>
57228753Smm#include <sys/signalvar.h>
58228753Smm#include <sys/systm.h>
59228753Smm#include <sys/vmmeter.h>
60228753Smm#include <machine/cpu.h>
61228753Smm#include <machine/pcb.h>
62228753Smm
63228753Smm/*
64228753Smm * Define the code needed before returning to user mode, for
65228753Smm * trap and syscall.
66228753Smm *
67228753Smm * MPSAFE
68228753Smm */
69228753Smmvoid
70228753Smmuserret(td, frame, oticks)
71228753Smm	struct thread *td;
72228753Smm	struct trapframe *frame;
73228753Smm	u_int oticks;
74228753Smm{
75231200Smm	struct proc *p = td->td_proc;
76231200Smm
77228753Smm	CTR3(KTR_SYSC, "userret: thread %p (pid %d, %s)", td, p->p_pid,
78231200Smm            p->p_comm);
79228753Smm#ifdef INVARIANTS
80231200Smm	/* Check that we called signotify() enough. */
81231200Smm	mtx_lock(&Giant);
82231200Smm	PROC_LOCK(p);
83231200Smm	mtx_lock_spin(&sched_lock);
84231200Smm	if (SIGPENDING(p) && ((p->p_sflag & PS_NEEDSIGCHK) == 0 ||
85231200Smm	    (td->td_flags & TDF_ASTPENDING) == 0))
86231200Smm		printf("failed to set signal flags properly for ast()\n");
87228753Smm	mtx_unlock_spin(&sched_lock);
88231200Smm	PROC_UNLOCK(p);
89228753Smm	mtx_unlock(&Giant);
90231200Smm#endif
91231200Smm
92231200Smm	/*
93231200Smm	 * Let the scheduler adjust our priority etc.
94228753Smm	 */
95228753Smm	sched_userret(td);
96228753Smm
97248616Smm	/*
98228753Smm	 * We need to check to see if we have to exit or wait due to a
99228753Smm	 * single threading requirement or some other STOP condition.
100228753Smm	 * Don't bother doing all the work if the stop bits are not set
101228753Smm	 * at this time.. If we miss it, we miss it.. no big deal.
102228753Smm	 */
103228753Smm	if (P_SHOULDSTOP(p)) {
104228753Smm		PROC_LOCK(p);
105228753Smm		thread_suspend_check(0);	/* Can suspend or kill */
106248616Smm		PROC_UNLOCK(p);
107228753Smm	}
108228753Smm
109228753Smm	/*
110228753Smm	 * Do special thread processing, e.g. upcall tweaking and such.
111228753Smm	 */
112228753Smm	if (p->p_flag & P_KSES) {
113228753Smm		thread_userret(td, frame);
114228753Smm	}
115228753Smm
116228753Smm	/*
117228753Smm	 * Charge system time if profiling.
118228753Smm	 *
119228753Smm	 * XXX should move PS_PROFIL to a place that can obviously be
120228753Smm	 * accessed safely without sched_lock.
121228753Smm	 */
122228753Smm	if (p->p_sflag & PS_PROFIL) {
123228753Smm		quad_t ticks;
124228753Smm
125228753Smm		mtx_lock_spin(&sched_lock);
126228753Smm		ticks = td->td_sticks - oticks;
127228753Smm		mtx_unlock_spin(&sched_lock);
128228753Smm		addupc_task(td, TRAPF_PC(frame), (u_int)ticks * psratio);
129228753Smm	}
130228753Smm}
131228753Smm
132228753Smm/*
133228753Smm * Process an asynchronous software trap.
134228753Smm * This is relatively easy.
135228753Smm * This function will return with preemption disabled.
136228753Smm */
137228753Smmvoid
138228753Smmast(struct trapframe *framep)
139228753Smm{
140231200Smm	struct thread *td;
141228753Smm	struct proc *p;
142228753Smm	struct kse *ke;
143228753Smm	struct ksegrp *kg;
144228753Smm	struct rlimit *rlim;
145228753Smm	u_int prticks, sticks;
146228753Smm	int sflag;
147228753Smm	int flags;
148228753Smm	int sig;
149228753Smm#if defined(DEV_NPX) && !defined(SMP)
150228753Smm	int ucode;
151228753Smm#endif
152228753Smm
153228753Smm	td = curthread;
154228753Smm	p = td->td_proc;
155228753Smm	kg = td->td_ksegrp;
156228753Smm
157228753Smm	CTR3(KTR_SYSC, "ast: thread %p (pid %d, %s)", td, p->p_pid,
158228753Smm            p->p_comm);
159228753Smm	KASSERT(TRAPF_USERMODE(framep), ("ast in kernel mode"));
160228753Smm#ifdef WITNESS
161228753Smm	if (witness_list(td))
162228753Smm		panic("Returning to user mode with mutex(s) held");
163228753Smm#endif
164228753Smm	mtx_assert(&Giant, MA_NOTOWNED);
165228753Smm	mtx_assert(&sched_lock, MA_NOTOWNED);
166228753Smm	td->td_frame = framep;
167228753Smm
168228753Smm	/*
169228753Smm	 * This updates the p_sflag's for the checks below in one
170228753Smm	 * "atomic" operation with turning off the astpending flag.
171228753Smm	 * If another AST is triggered while we are handling the
172228753Smm	 * AST's saved in sflag, the astpending flag will be set and
173228753Smm	 * ast() will be called again.
174248616Smm	 */
175228753Smm	mtx_lock_spin(&sched_lock);
176228753Smm	ke = td->td_kse;
177228753Smm	sticks = td->td_sticks;
178248616Smm	flags = td->td_flags;
179228753Smm	sflag = p->p_sflag;
180228753Smm	p->p_sflag &= ~(PS_ALRMPEND | PS_NEEDSIGCHK | PS_PROFPEND | PS_XCPU);
181228753Smm#ifdef MAC
182228753Smm	p->p_sflag &= ~PS_MACPEND;
183228753Smm#endif
184228753Smm	td->td_flags &= ~(TDF_ASTPENDING | TDF_NEEDRESCHED | TDF_OWEUPC);
185228753Smm	cnt.v_soft++;
186228753Smm	prticks = 0;
187228753Smm	if (flags & TDF_OWEUPC && sflag & PS_PROFIL) {
188228753Smm		prticks = p->p_stats->p_prof.pr_ticks;
189228753Smm		p->p_stats->p_prof.pr_ticks = 0;
190228753Smm	}
191228753Smm	mtx_unlock_spin(&sched_lock);
192228753Smm	/*
193228753Smm	 * XXXKSE While the fact that we owe a user profiling
194228753Smm	 * tick is stored per KSE in this code, the statistics
195228753Smm	 * themselves are still stored per process.
196248616Smm	 * This should probably change, by which I mean that
197228753Smm	 * possibly the location of both might change.
198228753Smm	 */
199228753Smm
200228753Smm	if (td->td_ucred != p->p_ucred)
201231200Smm		cred_update_thread(td);
202228753Smm	if (flags & TDF_OWEUPC && sflag & PS_PROFIL)
203228753Smm		addupc_task(td, p->p_stats->p_prof.pr_addr, prticks);
204228753Smm	if (sflag & PS_ALRMPEND) {
205228753Smm		PROC_LOCK(p);
206228753Smm		psignal(p, SIGVTALRM);
207228753Smm		PROC_UNLOCK(p);
208228753Smm	}
209228753Smm#if defined(DEV_NPX) && !defined(SMP)
210228753Smm	if (PCPU_GET(curpcb)->pcb_flags & PCB_NPXTRAP) {
211228753Smm		atomic_clear_int(&PCPU_GET(curpcb)->pcb_flags,
212228753Smm		    PCB_NPXTRAP);
213228753Smm		ucode = npxtrap();
214228753Smm		if (ucode != -1) {
215228753Smm			trapsignal(p, SIGFPE, ucode);
216228753Smm		}
217228753Smm	}
218228753Smm#endif
219228753Smm	if (sflag & PS_PROFPEND) {
220228753Smm		PROC_LOCK(p);
221228753Smm		psignal(p, SIGPROF);
222228753Smm		PROC_UNLOCK(p);
223228753Smm	}
224228753Smm	if (sflag & PS_XCPU) {
225228753Smm		PROC_LOCK(p);
226228753Smm		rlim = &p->p_rlimit[RLIMIT_CPU];
227228753Smm		if (p->p_runtime.sec >= rlim->rlim_max)
228228753Smm			killproc(p, "exceeded maximum CPU limit");
229228753Smm		else {
230228753Smm			psignal(p, SIGXCPU);
231228753Smm			mtx_lock_spin(&sched_lock);
232228753Smm			if (p->p_cpulimit < rlim->rlim_max)
233228753Smm				p->p_cpulimit += 5;
234228753Smm			mtx_unlock_spin(&sched_lock);
235228753Smm		}
236228753Smm		PROC_UNLOCK(p);
237228753Smm	}
238228753Smm#ifdef MAC
239228753Smm	if (sflag & PS_MACPEND)
240228753Smm		mac_thread_userret(td);
241228753Smm#endif
242228753Smm	if (flags & TDF_NEEDRESCHED) {
243228753Smm		mtx_lock_spin(&sched_lock);
244228753Smm		sched_prio(td, kg->kg_user_pri);
245228753Smm		p->p_stats->p_ru.ru_nivcsw++;
246228753Smm		mi_switch();
247228753Smm		mtx_unlock_spin(&sched_lock);
248228753Smm	}
249228753Smm	if (sflag & PS_NEEDSIGCHK) {
250228753Smm		PROC_LOCK(p);
251228753Smm		while ((sig = cursig(td)) != 0)
252228753Smm			postsig(sig);
253228753Smm		PROC_UNLOCK(p);
254228753Smm	}
255228753Smm
256228753Smm	userret(td, framep, sticks);
257228753Smm#ifdef DIAGNOSTIC
258228753Smm	cred_free_thread(td);
259228753Smm#endif
260228753Smm	mtx_assert(&Giant, MA_NOTOWNED);
261228753Smm}
262228753Smm