trap.c revision 82585
180708Sjake/*-
281899Sjake * Copyright (c) 2001, Jake Burkholder
381185Sjake * Copyright (C) 1994, David Greenman
481185Sjake * Copyright (c) 1990, 1993
581185Sjake *      The Regents of the University of California.  All rights reserved.
681185Sjake *
781185Sjake * This code is derived from software contributed to Berkeley by
881185Sjake * the University of Utah, and William Jolitz.
981185Sjake *
1081185Sjake * Redistribution and use in source and binary forms, with or without
1181185Sjake * modification, are permitted provided that the following conditions
1281185Sjake * are met:
1381185Sjake * 1. Redistributions of source code must retain the above copyright
1481185Sjake *    notice, this list of conditions and the following disclaimer.
1581185Sjake * 2. Redistributions in binary form must reproduce the above copyright
1681185Sjake *    notice, this list of conditions and the following disclaimer in the
1781185Sjake *    documentation and/or other materials provided with the distribution.
1881185Sjake * 3. All advertising materials mentioning features or use of this software
1981185Sjake *    must display the following acknowledgement:
2081185Sjake *      This product includes software developed by the University of
2181185Sjake *      California, Berkeley and its contributors.
2281185Sjake * 4. Neither the name of the University nor the names of its contributors
2381185Sjake *    may be used to endorse or promote products derived from this software
2481185Sjake *    without specific prior written permission.
2581185Sjake *
2681337Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2781185Sjake * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2881185Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2981337Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
3081185Sjake * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3181185Sjake * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3281185Sjake * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3381185Sjake * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3481185Sjake * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3581185Sjake * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3681185Sjake * SUCH DAMAGE.
3781185Sjake *
3881185Sjake *      from: @(#)trap.c        7.4 (Berkeley) 5/13/91
3981185Sjake * 	from: FreeBSD: src/sys/i386/i386/trap.c,v 1.197 2001/07/19
4080708Sjake * $FreeBSD: head/sys/sparc64/sparc64/trap.c 82585 2001-08-30 18:50:57Z dillon $
4180708Sjake */
4280708Sjake
4380709Sjake#include "opt_ddb.h"
4480709Sjake
4580708Sjake#include <sys/param.h>
4681135Stmm#include <sys/lock.h>
4780709Sjake#include <sys/mutex.h>
4880709Sjake#include <sys/systm.h>
4982006Sjake#include <sys/pioctl.h>
5080708Sjake#include <sys/proc.h>
5182006Sjake#include <sys/syscall.h>
5281135Stmm#include <sys/sysent.h>
5381135Stmm#include <sys/user.h>
5482006Sjake#include <sys/vmmeter.h>
5580708Sjake
5680709Sjake#include <vm/vm.h>
5781185Sjake#include <vm/pmap.h>
5881185Sjake#include <vm/vm_extern.h>
5980709Sjake#include <vm/vm_param.h>
6080709Sjake#include <vm/vm_kern.h>
6181185Sjake#include <vm/vm_map.h>
6280709Sjake#include <vm/vm_page.h>
6380709Sjake
6481387Sjake#include <machine/clock.h>
6580708Sjake#include <machine/frame.h>
6681387Sjake#include <machine/intr_machdep.h>
6781135Stmm#include <machine/pcb.h>
6880709Sjake#include <machine/pv.h>
6980709Sjake#include <machine/trap.h>
7082006Sjake#include <machine/tstate.h>
7180709Sjake#include <machine/tte.h>
7280709Sjake#include <machine/tlb.h>
7380709Sjake#include <machine/tsb.h>
7482006Sjake#include <machine/watch.h>
7580708Sjake
7680709Sjakevoid trap(struct trapframe *tf);
7781185Sjakeint trap_mmu_fault(struct proc *p, struct trapframe *tf);
7882006Sjakevoid syscall(struct proc *p, struct trapframe *tf, u_int sticks);
7980708Sjake
8080709Sjakeconst char *trap_msg[] = {
8180709Sjake	"reserved",
8280709Sjake	"power on reset",
8380709Sjake	"watchdog reset",
8480709Sjake	"externally initiated reset",
8580709Sjake	"software initiated reset",
8680709Sjake	"red state exception",
8780709Sjake	"instruction access exception",
8880709Sjake	"instruction access error",
8980709Sjake	"illegal instruction",
9080709Sjake	"privileged opcode",
9180709Sjake	"floating point disabled",
9280709Sjake	"floating point exception ieee 754",
9380709Sjake	"floating point exception other",
9480709Sjake	"tag overflow",
9580709Sjake	"division by zero",
9680709Sjake	"data access exception",
9780709Sjake	"data access error",
9880709Sjake	"memory address not aligned",
9980709Sjake	"lddf memory address not aligned",
10080709Sjake	"stdf memory address not aligned",
10180709Sjake	"privileged action",
10280709Sjake	"interrupt vector",
10380709Sjake	"physical address watchpoint",
10480709Sjake	"virtual address watchpoint",
10580709Sjake	"corrected ecc error",
10680709Sjake	"fast instruction access mmu miss",
10780709Sjake	"fast data access mmu miss",
10880709Sjake	"fast data access protection",
10981387Sjake	"clock",
11080709Sjake	"bad spill",
11180709Sjake	"bad fill",
11280709Sjake	"breakpoint",
11382006Sjake	"syscall",
11480709Sjake};
11580709Sjake
11680708Sjakevoid
11780709Sjaketrap(struct trapframe *tf)
11880708Sjake{
11981493Sjhb	u_int sticks;
12081135Stmm	struct proc *p;
12181387Sjake	int error;
12281135Stmm	int ucode;
12381387Sjake	int type;
12481135Stmm	int sig;
12582006Sjake	int mask;
12680709Sjake
12781185Sjake	KASSERT(PCPU_GET(curproc) != NULL, ("trap: curproc NULL"));
12881185Sjake	KASSERT(PCPU_GET(curpcb) != NULL, ("trap: curpcb NULL"));
12981185Sjake
13081185Sjake	p = PCPU_GET(curproc);
13181387Sjake	type = T_TYPE(tf->tf_type);
13281387Sjake	ucode = type;	/* XXX */
13381135Stmm
13481493Sjhb	if ((type & T_KERNEL) == 0)
13581387Sjake		sticks = p->p_sticks;
13681135Stmm
13781387Sjake	switch (type) {
13881135Stmm	case T_FP_DISABLED:
13981135Stmm		if (fp_enable_proc(p))
14081135Stmm			goto user;
14181135Stmm		else {
14281185Sjake			sig = SIGFPE;
14381135Stmm			goto trapsig;
14481135Stmm		}
14581135Stmm		break;
14681387Sjake	case T_IMMU_MISS:
14781387Sjake	case T_DMMU_MISS:
14881387Sjake	case T_DMMU_PROT:
14981387Sjake		mtx_lock(&Giant);
15081387Sjake		error = trap_mmu_fault(p, tf);
15181387Sjake		mtx_unlock(&Giant);
15281387Sjake		if (error == 0)
15381387Sjake			goto user;
15481387Sjake		break;
15581387Sjake	case T_INTR:
15681387Sjake		intr_dispatch(T_LEVEL(tf->tf_type), tf);
15781387Sjake		goto user;
15882006Sjake	case T_SYSCALL:
15982006Sjake		/* syscall() calls userret(), so we need goto out; */
16082006Sjake		syscall(p, tf, sticks);
16182006Sjake		goto out;
16280709Sjake#ifdef DDB
16380709Sjake	case T_BREAKPOINT | T_KERNEL:
16480709Sjake		if (kdb_trap(tf) != 0)
16581185Sjake			goto out;
16680709Sjake		break;
16780709Sjake#endif
16882006Sjake	case T_WATCH_VIRT | T_KERNEL:
16982006Sjake		/*
17082006Sjake		 * At the moment, just print the information from the trap,
17182006Sjake		 * remove the watchpoint, use evil magic to execute the
17282006Sjake		 * instruction (we temporarily save the instruction at
17382006Sjake		 * %tnpc, write a trap instruction, resume, and reset the
17482006Sjake		 * watch point when the trap arrives).
17582006Sjake		 * To make sure that no interrupt gets in between and creates
17682006Sjake		 * a potentially large window where the watchpoint is inactive,
17782006Sjake		 * disable interrupts temporarily.
17882006Sjake		 * This is obviously fragile and evilish.
17982006Sjake		 */
18082006Sjake		printf("Virtual watchpoint triggered, tpc=0x%lx, tnpc=0x%lx\n",
18182006Sjake		    tf->tf_tpc, tf->tf_tnpc);
18282006Sjake		PCPU_SET(wp_pstate, (tf->tf_tstate & TSTATE_PSTATE_MASK) >>
18382006Sjake		    TSTATE_PSTATE_SHIFT);
18482006Sjake		tf->tf_tstate &= ~TSTATE_IE;
18582006Sjake		wrpr(pstate, rdpr(pstate), PSTATE_IE);
18682006Sjake		PCPU_SET(wp_insn, *((u_int *)tf->tf_tnpc));
18782006Sjake		*((u_int *)tf->tf_tnpc) = 0x91d03002;	/* ta %xcc, 2 */
18882006Sjake		flush(tf->tf_tnpc);
18982006Sjake		PCPU_SET(wp_va, watch_virt_get(&mask));
19082006Sjake		PCPU_SET(wp_mask, mask);
19182006Sjake		watch_virt_clear();
19282006Sjake		goto out;
19382006Sjake	case T_RESTOREWP | T_KERNEL:
19482006Sjake		/*
19582006Sjake		 * Undo the tweaks tone for T_WATCH, reset the watch point and
19682006Sjake		 * contunue execution.
19782006Sjake		 * Note that here, we run with interrupts enabled, so there
19882006Sjake		 * is a small chance that we will be interrupted before we
19982006Sjake		 * could reset the watch point.
20082006Sjake		 */
20182006Sjake		tf->tf_tstate = (tf->tf_tstate & ~TSTATE_PSTATE_MASK) |
20282006Sjake		    PCPU_GET(wp_pstate) << TSTATE_PSTATE_SHIFT;
20382006Sjake		watch_virt_set_mask(PCPU_GET(wp_va), PCPU_GET(wp_mask));
20482006Sjake		*(u_int *)tf->tf_tpc = PCPU_GET(wp_insn);
20582006Sjake		flush(tf->tf_tpc);
20682006Sjake		goto out;
20781185Sjake	case T_DMMU_MISS | T_KERNEL:
20881185Sjake	case T_DMMU_PROT | T_KERNEL:
20981387Sjake		mtx_lock(&Giant);
21081387Sjake		error = trap_mmu_fault(p, tf);
21181387Sjake		mtx_unlock(&Giant);
21281387Sjake		if (error == 0)
21381185Sjake			goto out;
21481185Sjake		break;
21581387Sjake	case T_INTR | T_KERNEL:
21681387Sjake		intr_dispatch(T_LEVEL(tf->tf_type), tf);
21781387Sjake		goto out;
21880709Sjake	default:
21980709Sjake		break;
22080709Sjake	}
22181387Sjake	panic("trap: %s", trap_msg[type & ~T_KERNEL]);
22281135Stmm
22381135Stmmtrapsig:
22481135Stmm	/* Translate fault for emulators. */
22581135Stmm	if (p->p_sysent->sv_transtrap != NULL)
22681387Sjake		sig = (p->p_sysent->sv_transtrap)(sig, type);
22781135Stmm	trapsignal(p, sig, ucode);
22881135Stmmuser:
22981135Stmm	userret(p, tf, sticks);
23081135Stmm	if (mtx_owned(&Giant))
23181135Stmm		mtx_unlock(&Giant);
23281135Stmmout:
23381135Stmm	return;
23480708Sjake}
23581185Sjake
23681185Sjakeint
23781185Sjaketrap_mmu_fault(struct proc *p, struct trapframe *tf)
23881185Sjake{
23981185Sjake	struct mmuframe *mf;
24081185Sjake	struct vmspace *vm;
24181185Sjake	vm_offset_t va;
24281185Sjake	vm_prot_t type;
24381185Sjake	int rv;
24481185Sjake
24581185Sjake	KASSERT(p->p_vmspace != NULL, ("trap_dmmu_miss: vmspace NULL"));
24681185Sjake
24781387Sjake	type = 0;
24881185Sjake	rv = KERN_FAILURE;
24981185Sjake	mf = tf->tf_arg;
25081185Sjake	va = TLB_TAR_VA(mf->mf_tar);
25181185Sjake	switch (tf->tf_type) {
25281185Sjake	case T_DMMU_MISS | T_KERNEL:
25381185Sjake		/*
25481387Sjake		 * If the context is nucleus this is a soft fault on kernel
25581387Sjake		 * memory, just fault in the pages.
25681185Sjake		 */
25781387Sjake		if (TLB_TAR_CTX(mf->mf_tar) == TLB_CTX_KERNEL) {
25881387Sjake			rv = vm_fault(kernel_map, va, VM_PROT_READ,
25981387Sjake			    VM_FAULT_NORMAL);
26081185Sjake			break;
26181387Sjake		}
26281185Sjake
26381185Sjake		/*
26481387Sjake		 * Don't allow kernel mode faults on user memory unless
26581387Sjake		 * pcb_onfault is set.
26681387Sjake		 */
26781387Sjake		if (PCPU_GET(curpcb)->pcb_onfault == NULL)
26881387Sjake			break;
26981387Sjake		/* Fallthrough. */
27081387Sjake	case T_IMMU_MISS:
27181387Sjake	case T_DMMU_MISS:
27281387Sjake		/*
27381185Sjake		 * First try the tsb.  The primary tsb was already searched.
27481185Sjake		 */
27581185Sjake		vm = p->p_vmspace;
27681185Sjake		if (tsb_miss(&vm->vm_pmap, tf->tf_type, mf) == 0) {
27781185Sjake			rv = KERN_SUCCESS;
27881185Sjake			break;
27981185Sjake		}
28081185Sjake
28181185Sjake		/*
28281185Sjake		 * Not found, call the vm system.
28381185Sjake		 */
28481185Sjake
28581387Sjake		if (tf->tf_type == T_IMMU_MISS)
28681387Sjake			type = VM_PROT_EXECUTE | VM_PROT_READ;
28781387Sjake		else
28881387Sjake			type = VM_PROT_READ;
28981185Sjake
29081185Sjake		/*
29181185Sjake		 * Keep the process from being swapped out at this critical
29281185Sjake		 * time.
29381185Sjake		 */
29481185Sjake		PROC_LOCK(p);
29581185Sjake		++p->p_lock;
29681185Sjake		PROC_UNLOCK(p);
29781185Sjake
29881185Sjake		/*
29981185Sjake		 * Grow the stack if necessary.  vm_map_growstack only fails
30081185Sjake		 * if the va falls into a growable stack region and the stack
30181185Sjake		 * growth fails.  If it succeeds, or the va was not within a
30281185Sjake		 * growable stack region, fault in the user page.
30381185Sjake		 */
30481185Sjake		if (vm_map_growstack(p, va) != KERN_SUCCESS)
30581185Sjake			rv = KERN_FAILURE;
30681185Sjake		else
30781387Sjake			rv = vm_fault(&vm->vm_map, va, type, VM_FAULT_NORMAL);
30881185Sjake
30981185Sjake		/*
31081185Sjake		 * Now the process can be swapped again.
31181185Sjake		 */
31281185Sjake		PROC_LOCK(p);
31381185Sjake		--p->p_lock;
31481185Sjake		PROC_UNLOCK(p);
31581185Sjake		break;
31681185Sjake	case T_DMMU_PROT | T_KERNEL:
31781185Sjake		/*
31881387Sjake		 * Protection faults should not happen on kernel memory.
31981185Sjake		 */
32081387Sjake		if (TLB_TAR_CTX(mf->mf_tar) == TLB_CTX_KERNEL)
32181185Sjake			break;
32281185Sjake
32381185Sjake		/*
32481387Sjake		 * Don't allow kernel mode faults on user memory unless
32581387Sjake		 * pcb_onfault is set.
32681387Sjake		 */
32781387Sjake		if (PCPU_GET(curpcb)->pcb_onfault == NULL)
32881387Sjake			break;
32981387Sjake		/* Fallthrough. */
33081387Sjake	case T_DMMU_PROT:
33181387Sjake		/*
33281185Sjake		 * Only look in the tsb.  Write access to an unmapped page
33381185Sjake		 * causes a miss first, so the page must have already been
33481185Sjake		 * brought in by vm_fault, we just need to find the tte and
33581185Sjake		 * update the write bit.  XXX How do we tell them vm system
33681185Sjake		 * that we are now writing?
33781185Sjake		 */
33881185Sjake		vm = p->p_vmspace;
33981185Sjake		if (tsb_miss(&vm->vm_pmap, tf->tf_type, mf) == 0)
34081185Sjake			rv = KERN_SUCCESS;
34181185Sjake		break;
34281185Sjake	default:
34381185Sjake		break;
34481185Sjake	}
34581185Sjake	if (rv == KERN_SUCCESS)
34681185Sjake		return (0);
34781185Sjake	if (tf->tf_type & T_KERNEL) {
34881387Sjake		if (PCPU_GET(curpcb)->pcb_onfault != NULL &&
34981387Sjake		    TLB_TAR_CTX(mf->mf_tar) != TLB_CTX_KERNEL) {
35081387Sjake			tf->tf_tpc = (u_long)PCPU_GET(curpcb)->pcb_onfault;
35181185Sjake			tf->tf_tnpc = tf->tf_tpc + 4;
35281185Sjake			return (0);
35381185Sjake		}
35481185Sjake	}
35581185Sjake	return (rv == KERN_PROTECTION_FAILURE ? SIGBUS : SIGSEGV);
35681185Sjake}
35782006Sjake
35882006Sjake/* Maximum number of arguments that can be passed via the out registers. */
35982006Sjake#define	REG_MAXARGS	6
36082006Sjake
36182006Sjake/*
36282006Sjake * Syscall handler. The arguments to the syscall are passed in the o registers
36382006Sjake * by the caller, and are saved in the trap frame. The syscall number is passed
36482006Sjake * in %g1 (and also saved in the trap frame).
36582006Sjake */
36682006Sjakevoid
36782006Sjakesyscall(struct proc *p, struct trapframe *tf, u_int sticks)
36882006Sjake{
36982006Sjake	struct sysent *callp;
37082006Sjake	u_long code;
37182006Sjake	u_long tpc;
37282006Sjake	int reg;
37382006Sjake	int regcnt;
37482006Sjake	int narg;
37582006Sjake	int error;
37682006Sjake	register_t args[8];
37782006Sjake	void *argp;
37882006Sjake
37982006Sjake	narg = 0;
38082006Sjake	error = 0;
38182006Sjake	reg = 0;
38282006Sjake	regcnt = REG_MAXARGS;
38382006Sjake	code = tf->tf_global[1];
38482006Sjake	atomic_add_int(&cnt.v_syscall, 1);
38582006Sjake	/*
38682006Sjake	 * For syscalls, we don't want to retry the faulting instruction
38782006Sjake	 * (usually), instead we need to advance one instruction.
38882006Sjake	 */
38982006Sjake	tpc = tf->tf_tpc;
39082006Sjake	tf->tf_tpc = tf->tf_tnpc;
39182006Sjake	tf->tf_tnpc += 4;
39282006Sjake
39382006Sjake	if (p->p_sysent->sv_prepsyscall) {
39482006Sjake		/*
39582585Sdillon		 * The prep code is MP aware.
39682006Sjake		 */
39782006Sjake#if 0
39882006Sjake		(*p->p_sysent->sv_prepsyscall)(tf, args, &code, &params);
39982006Sjake#endif
40082006Sjake	} else 	if (code == SYS_syscall || code == SYS___syscall) {
40182006Sjake		code = tf->tf_out[reg++];
40282006Sjake		regcnt--;
40382006Sjake	}
40482006Sjake
40582006Sjake 	if (p->p_sysent->sv_mask)
40682006Sjake 		code &= p->p_sysent->sv_mask;
40782006Sjake
40882006Sjake 	if (code >= p->p_sysent->sv_size)
40982006Sjake 		callp = &p->p_sysent->sv_table[0];
41082006Sjake  	else
41182006Sjake 		callp = &p->p_sysent->sv_table[code];
41282006Sjake
41382006Sjake	narg = callp->sy_narg & SYF_ARGMASK;
41482006Sjake
41582006Sjake	if (narg <= regcnt)
41682006Sjake		argp = &tf->tf_out[reg];
41782006Sjake	else {
41882006Sjake		KASSERT(narg <= sizeof(args) / sizeof(args[0]),
41982006Sjake		    ("Too many syscall arguments!"));
42082006Sjake		argp = args;
42182006Sjake		bcopy(&tf->tf_out[reg], args, sizeof(args[0]) * regcnt);
42282006Sjake		error = copyin((void *)(tf->tf_out[6] + SPOFF +
42382006Sjake		    offsetof(struct frame, f_pad[6])),
42482006Sjake		    &args[reg + regcnt], (narg - regcnt) * sizeof(args[0]));
42582006Sjake		if (error != 0)
42682006Sjake			goto bad;
42782006Sjake	}
42882006Sjake
42982006Sjake	/*
43082006Sjake	 * Try to run the syscall without the MP lock if the syscall
43182006Sjake	 * is MP safe.
43282006Sjake	 */
43382006Sjake	if ((callp->sy_narg & SYF_MPSAFE) == 0)
43482006Sjake		mtx_lock(&Giant);
43582006Sjake
43682006Sjake#ifdef KTRACE
43782006Sjake	/*
43882006Sjake	 * We have to obtain the MP lock no matter what if
43982006Sjake	 * we are ktracing
44082006Sjake	 */
44182006Sjake	if (KTRPOINT(p, KTR_SYSCALL)) {
44282006Sjake		ktrsyscall(p->p_tracep, code, narg, args);
44382006Sjake	}
44482006Sjake#endif
44582006Sjake	p->p_retval[0] = 0;
44682006Sjake	p->p_retval[1] = tf->tf_out[1];
44782006Sjake
44882006Sjake	STOPEVENT(p, S_SCE, narg);	/* MP aware */
44982006Sjake
45082006Sjake	error = (*callp->sy_call)(p, argp);
45182006Sjake
45282006Sjake	/*
45382006Sjake	 * MP SAFE (we may or may not have the MP lock at this point)
45482006Sjake	 */
45582006Sjake	switch (error) {
45682006Sjake	case 0:
45782006Sjake		tf->tf_out[0] = p->p_retval[0];
45882006Sjake		tf->tf_out[1] = p->p_retval[1];
45982006Sjake		tf->tf_tstate &= ~TSTATE_XCC_C;
46082006Sjake		break;
46182006Sjake
46282006Sjake	case ERESTART:
46382006Sjake		/*
46482006Sjake		 * Undo the tpc advancement we have done above, we want to
46582006Sjake		 * reexecute the system call.
46682006Sjake		 */
46782006Sjake		tf->tf_tpc = tpc;
46882006Sjake		tf->tf_tnpc -= 4;
46982006Sjake		break;
47082006Sjake
47182006Sjake	case EJUSTRETURN:
47282006Sjake		break;
47382006Sjake
47482006Sjake	default:
47582006Sjakebad:
47682006Sjake 		if (p->p_sysent->sv_errsize) {
47782006Sjake 			if (error >= p->p_sysent->sv_errsize)
47882006Sjake  				error = -1;	/* XXX */
47982006Sjake   			else
48082006Sjake  				error = p->p_sysent->sv_errtbl[error];
48182006Sjake		}
48282006Sjake		tf->tf_out[0] = error;
48382006Sjake		tf->tf_tstate |= TSTATE_XCC_C;
48482006Sjake		break;
48582006Sjake	}
48682006Sjake
48782006Sjake	/*
48882006Sjake	 * Handle reschedule and other end-of-syscall issues
48982006Sjake	 */
49082006Sjake	userret(p, tf, sticks);
49182006Sjake
49282006Sjake#ifdef KTRACE
49382006Sjake	if (KTRPOINT(p, KTR_SYSRET)) {
49482006Sjake		ktrsysret(p->p_tracep, code, error, p->p_retval[0]);
49582006Sjake	}
49682006Sjake#endif
49782006Sjake
49882006Sjake	/*
49982585Sdillon	 * Release Giant if we had to get it.  Don't use mtx_owned(),
50082585Sdillon	 * we want to catch broken syscalls.
50182006Sjake	 */
50282585Sdillon	if ((callp->sy_narg & SYF_MPSAFE) == 0)
50382006Sjake		mtx_unlock(&Giant);
50482006Sjake
50582006Sjake	/*
50682006Sjake	 * This works because errno is findable through the
50782006Sjake	 * register set.  If we ever support an emulation where this
50882006Sjake	 * is not the case, this code will need to be revisited.
50982006Sjake	 */
51082006Sjake	STOPEVENT(p, S_SCX, code);
51182006Sjake
51282006Sjake#ifdef WITNESS
51382006Sjake	if (witness_list(p)) {
51482006Sjake		panic("system call %s returning with mutex(s) held\n",
51582006Sjake		    syscallnames[code]);
51682006Sjake	}
51782006Sjake#endif
51882006Sjake	mtx_assert(&sched_lock, MA_NOTOWNED);
51982006Sjake	mtx_assert(&Giant, MA_NOTOWNED);
52082006Sjake
52182006Sjake}
522