trap.c revision 83366
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 83366 2001-09-12 08:38:13Z julian $
4180708Sjake */
4280708Sjake
4380709Sjake#include "opt_ddb.h"
4482903Sjake#include "opt_ktr.h"
4580709Sjake
4680708Sjake#include <sys/param.h>
4782903Sjake#include <sys/ktr.h>
4881135Stmm#include <sys/lock.h>
4980709Sjake#include <sys/mutex.h>
5080709Sjake#include <sys/systm.h>
5182006Sjake#include <sys/pioctl.h>
5280708Sjake#include <sys/proc.h>
5382006Sjake#include <sys/syscall.h>
5481135Stmm#include <sys/sysent.h>
5581135Stmm#include <sys/user.h>
5682006Sjake#include <sys/vmmeter.h>
5780708Sjake
5880709Sjake#include <vm/vm.h>
5981185Sjake#include <vm/pmap.h>
6081185Sjake#include <vm/vm_extern.h>
6180709Sjake#include <vm/vm_param.h>
6280709Sjake#include <vm/vm_kern.h>
6381185Sjake#include <vm/vm_map.h>
6480709Sjake#include <vm/vm_page.h>
6580709Sjake
6681387Sjake#include <machine/clock.h>
6780708Sjake#include <machine/frame.h>
6881387Sjake#include <machine/intr_machdep.h>
6981135Stmm#include <machine/pcb.h>
7080709Sjake#include <machine/pv.h>
7180709Sjake#include <machine/trap.h>
7282006Sjake#include <machine/tstate.h>
7380709Sjake#include <machine/tte.h>
7480709Sjake#include <machine/tlb.h>
7580709Sjake#include <machine/tsb.h>
7682006Sjake#include <machine/watch.h>
7780708Sjake
7880709Sjakevoid trap(struct trapframe *tf);
7983366Sjulianint trap_mmu_fault(struct thread *td, struct trapframe *tf);
8083366Sjulianvoid syscall(struct thread *td, struct trapframe *tf, u_int sticks);
8180708Sjake
8282903Sjakeu_long trap_mask = 0xffffffffffffffffL & ~(1 << T_INTR);
8382903Sjake
8482903Sjakeextern char *syscallnames[];
8582903Sjake
8680709Sjakeconst char *trap_msg[] = {
8780709Sjake	"reserved",
8880709Sjake	"power on reset",
8980709Sjake	"watchdog reset",
9080709Sjake	"externally initiated reset",
9180709Sjake	"software initiated reset",
9280709Sjake	"red state exception",
9380709Sjake	"instruction access exception",
9480709Sjake	"instruction access error",
9580709Sjake	"illegal instruction",
9680709Sjake	"privileged opcode",
9780709Sjake	"floating point disabled",
9880709Sjake	"floating point exception ieee 754",
9980709Sjake	"floating point exception other",
10080709Sjake	"tag overflow",
10180709Sjake	"division by zero",
10280709Sjake	"data access exception",
10380709Sjake	"data access error",
10480709Sjake	"memory address not aligned",
10580709Sjake	"lddf memory address not aligned",
10680709Sjake	"stdf memory address not aligned",
10780709Sjake	"privileged action",
10880709Sjake	"interrupt vector",
10980709Sjake	"physical address watchpoint",
11080709Sjake	"virtual address watchpoint",
11180709Sjake	"corrected ecc error",
11280709Sjake	"fast instruction access mmu miss",
11380709Sjake	"fast data access mmu miss",
11480709Sjake	"fast data access protection",
11582903Sjake	"spill",
11682903Sjake	"fill",
11782903Sjake	"fill",
11880709Sjake	"breakpoint",
11982006Sjake	"syscall",
12082903Sjake	"trap instruction",
12180709Sjake};
12280709Sjake
12380708Sjakevoid
12480709Sjaketrap(struct trapframe *tf)
12580708Sjake{
12681493Sjhb	u_int sticks;
12783366Sjulian	struct thread *td;
12881135Stmm	struct proc *p;
12981387Sjake	int error;
13081135Stmm	int ucode;
13181387Sjake	int type;
13281135Stmm	int sig;
13382006Sjake	int mask;
13480709Sjake
13583366Sjulian	KASSERT(PCPU_GET(curthread) != NULL, ("trap: curthread NULL"));
13681185Sjake	KASSERT(PCPU_GET(curpcb) != NULL, ("trap: curpcb NULL"));
13781185Sjake
13882903Sjake	error = 0;
13983366Sjulian	td = PCPU_GET(curthread);
14083366Sjulian	p = td->td_proc;
14182903Sjake	type = tf->tf_type;
14281387Sjake	ucode = type;	/* XXX */
14382903Sjake	sticks = 0;
14481135Stmm
14582903Sjake#if KTR_COMPILE & KTR_TRAP
14682903Sjake	if (trap_mask & (1 << (type & ~T_KERNEL))) {
14782903Sjake		CTR5(KTR_TRAP, "trap: %s type=%s (%s) ws=%#lx ow=%#lx",
14882903Sjake		    p->p_comm, trap_msg[type & ~T_KERNEL],
14982903Sjake		    ((type & T_KERNEL) ? "kernel" : "user"),
15082903Sjake		    rdpr(wstate), rdpr(otherwin));
15182903Sjake	}
15282903Sjake#endif
15382903Sjake
15482903Sjake	if (type == T_SYSCALL)
15582903Sjake		cnt.v_syscall++;
15682903Sjake	else if ((type & ~T_KERNEL) == T_INTR)
15782903Sjake		cnt.v_intr++;
15882903Sjake	else
15982903Sjake		cnt.v_trap++;
16082903Sjake
16182903Sjake	if ((type & T_KERNEL) == 0) {
16283366Sjulian		sticks = td->td_kse->ke_sticks;
16383366Sjulian		td->td_frame = tf;
16482903Sjake	}
16581135Stmm
16681387Sjake	switch (type) {
16782903Sjake	case T_ALIGN:
16882903Sjake	case T_ALIGN_LDDF:
16982903Sjake	case T_ALIGN_STDF:
17082903Sjake		sig = SIGBUS;
17182903Sjake		goto trapsig;
17282903Sjake	case T_BREAKPOINT:
17382903Sjake		sig = SIGTRAP;
17482903Sjake		goto trapsig;
17582903Sjake	case T_DIVIDE:
17682903Sjake		sig = SIGFPE;
17782903Sjake		goto trapsig;
17881135Stmm	case T_FP_DISABLED:
17983366Sjulian		if (fp_enable_thread(td))
18081135Stmm			goto user;
18182903Sjake		/* Fallthrough. */
18282903Sjake	case T_FP_IEEE:
18382903Sjake	case T_FP_OTHER:
18482903Sjake		sig = SIGFPE;
18582903Sjake		goto trapsig;
18682903Sjake	case T_DATA_ERROR:
18782903Sjake	case T_DATA_EXCPTN:
18882903Sjake	case T_INSN_ERROR:
18982903Sjake	case T_INSN_EXCPTN:
19082903Sjake		sig = SIGILL;	/* XXX */
19182903Sjake		goto trapsig;
19281387Sjake	case T_DMMU_MISS:
19381387Sjake	case T_DMMU_PROT:
19482903Sjake	case T_IMMU_MISS:
19583366Sjulian		error = trap_mmu_fault(td, tf);
19681387Sjake		if (error == 0)
19781387Sjake			goto user;
19882903Sjake		sig = error;
19982903Sjake		goto trapsig;
20082903Sjake	case T_FILL:
20183366Sjulian		if (rwindow_load(td, tf, 2))
20283366Sjulian			sigexit(td, SIGILL);
20382903Sjake		goto out;
20482903Sjake	case T_FILL_RET:
20583366Sjulian		if (rwindow_load(td, tf, 1))
20683366Sjulian			sigexit(td, SIGILL);
20782903Sjake		goto out;
20882903Sjake	case T_INSN_ILLEGAL:
20982903Sjake		sig = SIGILL;
21082903Sjake		goto trapsig;
21181387Sjake	case T_INTR:
21282903Sjake		intr_dispatch(tf->tf_arg, tf);
21382903Sjake		goto out;
21482903Sjake	case T_PRIV_ACTION:
21582903Sjake	case T_PRIV_OPCODE:
21682903Sjake		sig = SIGBUS;
21782903Sjake		goto trapsig;
21882903Sjake	case T_SOFT:
21982903Sjake		sig = SIGILL;
22082903Sjake		goto trapsig;
22182903Sjake	case T_SPILL:
22283366Sjulian		if (rwindow_save(td))
22383366Sjulian			sigexit(td, SIGILL);
22482903Sjake		goto out;
22582006Sjake	case T_SYSCALL:
22682006Sjake		/* syscall() calls userret(), so we need goto out; */
22783366Sjulian		syscall(td, tf, sticks);
22882006Sjake		goto out;
22982903Sjake	case T_TAG_OVFLW:
23082903Sjake		sig = SIGEMT;
23182903Sjake		goto trapsig;
23280709Sjake#ifdef DDB
23380709Sjake	case T_BREAKPOINT | T_KERNEL:
23480709Sjake		if (kdb_trap(tf) != 0)
23581185Sjake			goto out;
23680709Sjake		break;
23780709Sjake#endif
23882903Sjake	case T_DMMU_MISS | T_KERNEL:
23982903Sjake	case T_DMMU_PROT | T_KERNEL:
24083366Sjulian		error = trap_mmu_fault(td, tf);
24182903Sjake		if (error == 0)
24282903Sjake			goto out;
24382903Sjake		break;
24482903Sjake	case T_INTR | T_KERNEL:
24582903Sjake		intr_dispatch(tf->tf_arg, tf);
24682903Sjake		goto out;
24782006Sjake	case T_WATCH_VIRT | T_KERNEL:
24882006Sjake		/*
24982006Sjake		 * At the moment, just print the information from the trap,
25082006Sjake		 * remove the watchpoint, use evil magic to execute the
25182006Sjake		 * instruction (we temporarily save the instruction at
25282006Sjake		 * %tnpc, write a trap instruction, resume, and reset the
25382006Sjake		 * watch point when the trap arrives).
25482006Sjake		 * To make sure that no interrupt gets in between and creates
25582006Sjake		 * a potentially large window where the watchpoint is inactive,
25682006Sjake		 * disable interrupts temporarily.
25782006Sjake		 * This is obviously fragile and evilish.
25882006Sjake		 */
25982006Sjake		printf("Virtual watchpoint triggered, tpc=0x%lx, tnpc=0x%lx\n",
26082006Sjake		    tf->tf_tpc, tf->tf_tnpc);
26182006Sjake		PCPU_SET(wp_pstate, (tf->tf_tstate & TSTATE_PSTATE_MASK) >>
26282006Sjake		    TSTATE_PSTATE_SHIFT);
26382006Sjake		tf->tf_tstate &= ~TSTATE_IE;
26482006Sjake		wrpr(pstate, rdpr(pstate), PSTATE_IE);
26582006Sjake		PCPU_SET(wp_insn, *((u_int *)tf->tf_tnpc));
26682006Sjake		*((u_int *)tf->tf_tnpc) = 0x91d03002;	/* ta %xcc, 2 */
26782006Sjake		flush(tf->tf_tnpc);
26882006Sjake		PCPU_SET(wp_va, watch_virt_get(&mask));
26982006Sjake		PCPU_SET(wp_mask, mask);
27082006Sjake		watch_virt_clear();
27182006Sjake		goto out;
27282006Sjake	case T_RESTOREWP | T_KERNEL:
27382006Sjake		/*
27482006Sjake		 * Undo the tweaks tone for T_WATCH, reset the watch point and
27582006Sjake		 * contunue execution.
27682006Sjake		 * Note that here, we run with interrupts enabled, so there
27782006Sjake		 * is a small chance that we will be interrupted before we
27882006Sjake		 * could reset the watch point.
27982006Sjake		 */
28082006Sjake		tf->tf_tstate = (tf->tf_tstate & ~TSTATE_PSTATE_MASK) |
28182006Sjake		    PCPU_GET(wp_pstate) << TSTATE_PSTATE_SHIFT;
28282006Sjake		watch_virt_set_mask(PCPU_GET(wp_va), PCPU_GET(wp_mask));
28382006Sjake		*(u_int *)tf->tf_tpc = PCPU_GET(wp_insn);
28482006Sjake		flush(tf->tf_tpc);
28582006Sjake		goto out;
28680709Sjake	default:
28780709Sjake		break;
28880709Sjake	}
28981387Sjake	panic("trap: %s", trap_msg[type & ~T_KERNEL]);
29081135Stmm
29181135Stmmtrapsig:
29281135Stmm	/* Translate fault for emulators. */
29381135Stmm	if (p->p_sysent->sv_transtrap != NULL)
29481387Sjake		sig = (p->p_sysent->sv_transtrap)(sig, type);
29581135Stmm	trapsignal(p, sig, ucode);
29681135Stmmuser:
29783366Sjulian	userret(td, tf, sticks);
29881135Stmmout:
29982903Sjake#if KTR_COMPILE & KTR_TRAP
30082903Sjake	if (trap_mask & (1 << (type & ~T_KERNEL))) {
30182903Sjake		CTR1(KTR_TRAP, "trap: p=%p return", p);
30282903Sjake	}
30382903Sjake#endif
30481135Stmm	return;
30580708Sjake}
30681185Sjake
30781185Sjakeint
30883366Sjuliantrap_mmu_fault(struct thread *td, struct trapframe *tf)
30981185Sjake{
31081185Sjake	struct mmuframe *mf;
31181185Sjake	struct vmspace *vm;
31282903Sjake	struct stte *stp;
31382903Sjake	struct pcb *pcb;
31482903Sjake	struct tte tte;
31583366Sjulian	struct proc *p;
31681185Sjake	vm_offset_t va;
31782903Sjake	vm_prot_t prot;
31882903Sjake	u_long ctx;
31982903Sjake	pmap_t pm;
32082903Sjake	int flags;
32182903Sjake	int type;
32281185Sjake	int rv;
32381185Sjake
32483366Sjulian	p = td->td_proc;
32581185Sjake	KASSERT(p->p_vmspace != NULL, ("trap_dmmu_miss: vmspace NULL"));
32681185Sjake
32782903Sjake	rv = KERN_SUCCESS;
32882903Sjake	mf = (struct mmuframe *)tf->tf_arg;
32982903Sjake	ctx = TLB_TAR_CTX(mf->mf_tar);
33082903Sjake	pcb = PCPU_GET(curpcb);
33182903Sjake	type = tf->tf_type & ~T_KERNEL;
33281185Sjake	va = TLB_TAR_VA(mf->mf_tar);
33381185Sjake
33483366Sjulian	CTR4(KTR_TRAP, "trap_mmu_fault: td=%p pm_ctx=%#lx va=%#lx ctx=%#lx",
33583366Sjulian	    td, p->p_vmspace->vm_pmap.pm_context, va, ctx);
33681185Sjake
33782903Sjake	if (type == T_DMMU_PROT) {
33882903Sjake		prot = VM_PROT_WRITE;
33982903Sjake		flags = VM_FAULT_DIRTY;
34082903Sjake	} else {
34182903Sjake		if (type == T_DMMU_MISS)
34282903Sjake			prot = VM_PROT_READ;
34381387Sjake		else
34482903Sjake			prot = VM_PROT_READ | VM_PROT_EXECUTE;
34582903Sjake		flags = VM_FAULT_NORMAL;
34682903Sjake	}
34781185Sjake
34882903Sjake	if (ctx == TLB_CTX_KERNEL) {
34982903Sjake		mtx_lock(&Giant);
35082903Sjake		rv = vm_fault(kernel_map, va, prot, VM_FAULT_NORMAL);
35182903Sjake		mtx_unlock(&Giant);
35282903Sjake		if (rv == KERN_SUCCESS) {
35382903Sjake			stp = tsb_kvtostte(va);
35482903Sjake			tte = stp->st_tte;
35582903Sjake			if (type == T_IMMU_MISS)
35682903Sjake				tlb_store(TLB_DTLB | TLB_ITLB, va, ctx, tte);
35782903Sjake			else
35882903Sjake				tlb_store(TLB_DTLB, va, ctx, tte);
35982903Sjake		}
36082903Sjake	} else if (tf->tf_type & T_KERNEL &&
36183366Sjulian	    (td->td_intr_nesting_level != 0 || pcb->pcb_onfault == NULL)) {
36282903Sjake		rv = KERN_FAILURE;
36382903Sjake	} else {
36482903Sjake		mtx_lock(&Giant);
36582903Sjake		vm = p->p_vmspace;
36682903Sjake		pm = &vm->vm_pmap;
36782903Sjake		stp = tsb_stte_lookup(pm, va);
36882903Sjake		if (stp == NULL || type == T_DMMU_PROT) {
36982903Sjake			/*
37082903Sjake			 * Keep the process from being swapped out at this
37182903Sjake			 * critical time.
37282903Sjake			 */
37382903Sjake			PROC_LOCK(p);
37482903Sjake			++p->p_lock;
37582903Sjake			PROC_UNLOCK(p);
37682903Sjake
37782903Sjake			/*
37882903Sjake			 * Grow the stack if necessary.  vm_map_growstack only
37982903Sjake			 * fails if the va falls into a growable stack region
38082903Sjake			 * and the stack growth fails.  If it succeeds, or the
38182903Sjake			 * va was not within a growable stack region, fault in
38282903Sjake			 * the user page.
38382903Sjake			 */
38482903Sjake			if (vm_map_growstack(p, va) != KERN_SUCCESS)
38582903Sjake				rv = KERN_FAILURE;
38682903Sjake			else
38782903Sjake				rv = vm_fault(&vm->vm_map, va, prot, flags);
38882903Sjake
38982903Sjake			/*
39082903Sjake			 * Now the process can be swapped again.
39182903Sjake			 */
39282903Sjake			PROC_LOCK(p);
39382903Sjake			--p->p_lock;
39482903Sjake			PROC_UNLOCK(p);
39582903Sjake		} else if (type == T_IMMU_MISS) {
39682903Sjake			if ((stp->st_tte.tte_data & TD_EXEC) == 0)
39782903Sjake				rv = KERN_FAILURE;
39882903Sjake			else
39982903Sjake				tlb_store(TLB_DTLB | TLB_ITLB, va, ctx,
40082903Sjake				    stp->st_tte);
40182903Sjake		} else if (type == T_DMMU_PROT &&
40282903Sjake			   (stp->st_tte.tte_data & TD_SW) == 0) {
40381185Sjake			rv = KERN_FAILURE;
40482903Sjake		} else {
40582903Sjake			tlb_store(TLB_DTLB, va, ctx, stp->st_tte);
40682903Sjake		}
40782903Sjake		mtx_unlock(&Giant);
40881185Sjake	}
40982903Sjake	CTR3(KTR_TRAP, "trap_mmu_fault: return p=%p va=%#lx rv=%d", p, va, rv);
41081185Sjake	if (rv == KERN_SUCCESS)
41181185Sjake		return (0);
41281185Sjake	if (tf->tf_type & T_KERNEL) {
41382903Sjake		if (pcb->pcb_onfault != NULL && ctx != TLB_CTX_KERNEL) {
41482903Sjake			tf->tf_tpc = (u_long)pcb->pcb_onfault;
41581185Sjake			tf->tf_tnpc = tf->tf_tpc + 4;
41681185Sjake			return (0);
41781185Sjake		}
41881185Sjake	}
41981185Sjake	return (rv == KERN_PROTECTION_FAILURE ? SIGBUS : SIGSEGV);
42081185Sjake}
42182006Sjake
42282006Sjake/* Maximum number of arguments that can be passed via the out registers. */
42382006Sjake#define	REG_MAXARGS	6
42482006Sjake
42582006Sjake/*
42682006Sjake * Syscall handler. The arguments to the syscall are passed in the o registers
42782006Sjake * by the caller, and are saved in the trap frame. The syscall number is passed
42882006Sjake * in %g1 (and also saved in the trap frame).
42982006Sjake */
43082006Sjakevoid
43183366Sjuliansyscall(struct thread *td, struct trapframe *tf, u_int sticks)
43282006Sjake{
43382006Sjake	struct sysent *callp;
43483366Sjulian	struct proc *p;
43582006Sjake	u_long code;
43682006Sjake	u_long tpc;
43782006Sjake	int reg;
43882006Sjake	int regcnt;
43982006Sjake	int narg;
44082006Sjake	int error;
44182006Sjake	register_t args[8];
44282903Sjake	register_t *argp;
44382006Sjake
44482006Sjake	narg = 0;
44582006Sjake	error = 0;
44682006Sjake	reg = 0;
44782006Sjake	regcnt = REG_MAXARGS;
44882006Sjake	code = tf->tf_global[1];
44983366Sjulian	p = td->td_proc;
45082006Sjake	/*
45182006Sjake	 * For syscalls, we don't want to retry the faulting instruction
45282006Sjake	 * (usually), instead we need to advance one instruction.
45382006Sjake	 */
45482006Sjake	tpc = tf->tf_tpc;
45582006Sjake	tf->tf_tpc = tf->tf_tnpc;
45682006Sjake	tf->tf_tnpc += 4;
45782006Sjake
45882006Sjake	if (p->p_sysent->sv_prepsyscall) {
45982006Sjake		/*
46082585Sdillon		 * The prep code is MP aware.
46182006Sjake		 */
46282006Sjake#if 0
46382006Sjake		(*p->p_sysent->sv_prepsyscall)(tf, args, &code, &params);
46482006Sjake#endif
46582006Sjake	} else 	if (code == SYS_syscall || code == SYS___syscall) {
46682006Sjake		code = tf->tf_out[reg++];
46782006Sjake		regcnt--;
46882006Sjake	}
46982006Sjake
47082006Sjake 	if (p->p_sysent->sv_mask)
47182006Sjake 		code &= p->p_sysent->sv_mask;
47282006Sjake
47382006Sjake 	if (code >= p->p_sysent->sv_size)
47482006Sjake 		callp = &p->p_sysent->sv_table[0];
47582006Sjake  	else
47682006Sjake 		callp = &p->p_sysent->sv_table[code];
47782006Sjake
47882006Sjake	narg = callp->sy_narg & SYF_ARGMASK;
47982006Sjake
48082006Sjake	if (narg <= regcnt)
48182006Sjake		argp = &tf->tf_out[reg];
48282006Sjake	else {
48382006Sjake		KASSERT(narg <= sizeof(args) / sizeof(args[0]),
48482006Sjake		    ("Too many syscall arguments!"));
48582006Sjake		argp = args;
48682006Sjake		bcopy(&tf->tf_out[reg], args, sizeof(args[0]) * regcnt);
48782006Sjake		error = copyin((void *)(tf->tf_out[6] + SPOFF +
48882006Sjake		    offsetof(struct frame, f_pad[6])),
48982006Sjake		    &args[reg + regcnt], (narg - regcnt) * sizeof(args[0]));
49082006Sjake		if (error != 0)
49182006Sjake			goto bad;
49282006Sjake	}
49382006Sjake
49483366Sjulian	CTR5(KTR_SYSC, "syscall: td=%p %s(%#lx, %#lx, %#lx)", td,
49582903Sjake	    syscallnames[code], argp[0], argp[1], argp[2]);
49682903Sjake
49782006Sjake	/*
49882006Sjake	 * Try to run the syscall without the MP lock if the syscall
49982006Sjake	 * is MP safe.
50082006Sjake	 */
50182006Sjake	if ((callp->sy_narg & SYF_MPSAFE) == 0)
50282006Sjake		mtx_lock(&Giant);
50382006Sjake
50482006Sjake#ifdef KTRACE
50582006Sjake	/*
50682006Sjake	 * We have to obtain the MP lock no matter what if
50782006Sjake	 * we are ktracing
50882006Sjake	 */
50982006Sjake	if (KTRPOINT(p, KTR_SYSCALL)) {
51082006Sjake		ktrsyscall(p->p_tracep, code, narg, args);
51182006Sjake	}
51282006Sjake#endif
51383366Sjulian	td->td_retval[0] = 0;
51483366Sjulian	td->td_retval[1] = tf->tf_out[1];
51582006Sjake
51682006Sjake	STOPEVENT(p, S_SCE, narg);	/* MP aware */
51782006Sjake
51883366Sjulian	error = (*callp->sy_call)(td, argp);
51982903Sjake
52082903Sjake	CTR5(KTR_SYSC, "syscall: p=%p error=%d %s return %#lx %#lx ", p,
52183366Sjulian	    error, syscallnames[code], td->td_retval[0], td->td_retval[1]);
52282006Sjake
52382006Sjake	/*
52482006Sjake	 * MP SAFE (we may or may not have the MP lock at this point)
52582006Sjake	 */
52682006Sjake	switch (error) {
52782006Sjake	case 0:
52883366Sjulian		tf->tf_out[0] = td->td_retval[0];
52983366Sjulian		tf->tf_out[1] = td->td_retval[1];
53082006Sjake		tf->tf_tstate &= ~TSTATE_XCC_C;
53182006Sjake		break;
53282006Sjake
53382006Sjake	case ERESTART:
53482006Sjake		/*
53582006Sjake		 * Undo the tpc advancement we have done above, we want to
53682006Sjake		 * reexecute the system call.
53782006Sjake		 */
53882006Sjake		tf->tf_tpc = tpc;
53982006Sjake		tf->tf_tnpc -= 4;
54082006Sjake		break;
54182006Sjake
54282006Sjake	case EJUSTRETURN:
54382006Sjake		break;
54482006Sjake
54582006Sjake	default:
54682006Sjakebad:
54782006Sjake 		if (p->p_sysent->sv_errsize) {
54882006Sjake 			if (error >= p->p_sysent->sv_errsize)
54982006Sjake  				error = -1;	/* XXX */
55082006Sjake   			else
55182006Sjake  				error = p->p_sysent->sv_errtbl[error];
55282006Sjake		}
55382006Sjake		tf->tf_out[0] = error;
55482006Sjake		tf->tf_tstate |= TSTATE_XCC_C;
55582006Sjake		break;
55682006Sjake	}
55782006Sjake
55882006Sjake	/*
55982006Sjake	 * Handle reschedule and other end-of-syscall issues
56082006Sjake	 */
56183366Sjulian	userret(td, tf, sticks);
56282006Sjake
56382006Sjake#ifdef KTRACE
56482006Sjake	if (KTRPOINT(p, KTR_SYSRET)) {
56583366Sjulian		ktrsysret(p->p_tracep, code, error, td->td_retval[0]);
56682006Sjake	}
56782006Sjake#endif
56882006Sjake
56982006Sjake	/*
57082585Sdillon	 * Release Giant if we had to get it.  Don't use mtx_owned(),
57182585Sdillon	 * we want to catch broken syscalls.
57282006Sjake	 */
57382585Sdillon	if ((callp->sy_narg & SYF_MPSAFE) == 0)
57482006Sjake		mtx_unlock(&Giant);
57582006Sjake
57682006Sjake	/*
57782006Sjake	 * This works because errno is findable through the
57882006Sjake	 * register set.  If we ever support an emulation where this
57982006Sjake	 * is not the case, this code will need to be revisited.
58082006Sjake	 */
58182006Sjake	STOPEVENT(p, S_SCX, code);
58282006Sjake
58382006Sjake#ifdef WITNESS
58483366Sjulian	if (witness_list(td)) {
58582006Sjake		panic("system call %s returning with mutex(s) held\n",
58682006Sjake		    syscallnames[code]);
58782006Sjake	}
58882006Sjake#endif
58982006Sjake	mtx_assert(&sched_lock, MA_NOTOWNED);
59082006Sjake	mtx_assert(&Giant, MA_NOTOWNED);
59182006Sjake
59282006Sjake}
593