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, ¶ms); 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