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