New syscall entry implementation based on the Alpha version
as hacked by mycroft. - Use syscall_intern() to give a process a plain or fancy syscall based on ktrace flags. - Avoid copying from the trapframe into a local array as much as possible. Yields roughly 5% improvement on a 25MHz R3000 (DECstation 5000/200) on a simple syscall benchmark. There's still some work that can be done using __HAVE_MINIMAL_EMUL.
This commit is contained in:
parent
f20b78bb5d
commit
9f5a22b3ee
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: files.mips,v 1.29 2000/10/31 22:46:35 jeffs Exp $
|
||||
# $NetBSD: files.mips,v 1.30 2001/01/16 06:01:26 thorpej Exp $
|
||||
#
|
||||
|
||||
defopt opt_cputype.h NOTYET # MIPS1 MIPS2 MIPS3 MIPS4 MIPS5
|
||||
|
@ -20,6 +20,7 @@ file arch/mips/mips/kgdb_machdep.c kgdb
|
|||
file arch/mips/mips/mem.c
|
||||
file arch/mips/mips/mips_mcclock.c mcclock # CPU speed via mcclock
|
||||
file arch/mips/mips/pmap.c
|
||||
file arch/mips/mips/syscall.c # syscalls
|
||||
file arch/mips/mips/trap.c # interrupt, trap handlers
|
||||
file arch/mips/mips/vm_machdep.c
|
||||
file arch/mips/mips/mips_machdep.c # shared mips machdep.c
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: proc.h,v 1.11 2001/01/14 21:18:39 thorpej Exp $ */
|
||||
/* $NetBSD: proc.h,v 1.12 2001/01/16 06:01:26 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
|
@ -40,6 +40,9 @@
|
|||
|
||||
#ifndef _MIPS_PROC_H_
|
||||
#define _MIPS_PROC_H_
|
||||
|
||||
struct proc;
|
||||
|
||||
/*
|
||||
* Machine-dependent part of the proc structure for MIPS
|
||||
*/
|
||||
|
@ -50,6 +53,8 @@ struct mdproc {
|
|||
int md_ss_addr; /* single step address for ptrace */
|
||||
int md_ss_instr; /* single step instruction for ptrace */
|
||||
__volatile int md_astpending; /* AST pending on return to userland */
|
||||
/* syscall entry for this process */
|
||||
void (*md_syscall)(struct proc *, u_int, u_int, u_int);
|
||||
};
|
||||
|
||||
/* md_flags */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: types.h,v 1.26 2001/01/14 22:32:57 thorpej Exp $ */
|
||||
/* $NetBSD: types.h,v 1.27 2001/01/16 06:01:26 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992, 1993
|
||||
|
@ -44,8 +44,6 @@
|
|||
#include <sys/cdefs.h>
|
||||
#include <machine/int_types.h>
|
||||
|
||||
#define __HAVE_AST_PERPROC
|
||||
|
||||
/*
|
||||
* Note that mips_reg_t is distinct from the register_t defined
|
||||
* in <types.h> to allow these structures to be as hidden from
|
||||
|
@ -103,6 +101,8 @@ typedef int32_t register_t;
|
|||
|
||||
#define __SWAP_BROKEN
|
||||
|
||||
#define __HAVE_AST_PERPROC
|
||||
#define __HAVE_SYSCALL_INTERN
|
||||
#ifdef MIPS3
|
||||
#define __HAVE_CPU_COUNTER
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: genassym.cf,v 1.22 2001/01/14 21:18:39 thorpej Exp $
|
||||
# $NetBSD: genassym.cf,v 1.23 2001/01/16 06:01:26 thorpej Exp $
|
||||
#
|
||||
# Copyright (c) 1997
|
||||
# Jonathan Stone. All rights reserved.
|
||||
|
@ -65,6 +65,7 @@ define P_MD_REGS offsetof(struct proc, p_md.md_regs)
|
|||
define P_MD_UPTE_0 offsetof(struct proc, p_md.md_upte[0])
|
||||
define P_MD_UPTE_1 offsetof(struct proc, p_md.md_upte[1])
|
||||
define P_MD_ASTPENDING offsetof(struct proc, p_md.md_astpending)
|
||||
define P_MD_SYSCALL offsetof(struct proc, p_md.md_syscall)
|
||||
|
||||
define U_PCB_FPREGS offsetof(struct user, u_pcb.pcb_fpregs)
|
||||
define U_PCB_CONTEXT offsetof(struct user, u_pcb.pcb_context)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: locore_mips1.S,v 1.50 2001/01/14 21:18:39 thorpej Exp $ */
|
||||
/* $NetBSD: locore_mips1.S,v 1.51 2001/01/16 06:01:26 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
|
@ -404,22 +404,23 @@ NESTED_NOPROFILE(mips1_SystemCall, CALLFRAME_SIZ, ra)
|
|||
sw a1, FRAME_A1(k1)
|
||||
sw a2, FRAME_A2(k1)
|
||||
sw a3, FRAME_A3(k1)
|
||||
lw a0, _C_LABEL(curproc) # 1st arg is curproc
|
||||
mfhi v1
|
||||
#sw t0, FRAME_T0(k1) # no need to save temp regs
|
||||
#sw t1, FRAME_T1(k1)
|
||||
#sw t2, FRAME_T2(k1)
|
||||
#sw t3, FRAME_T3(k1)
|
||||
mfc0 a0, MIPS_COP_0_STATUS # 1st arg is STATUS
|
||||
mfc0 a1, MIPS_COP_0_STATUS # 2nd arg is STATUS
|
||||
#sw t4, FRAME_T4(k1)
|
||||
#sw t5, FRAME_T5(k1)
|
||||
#sw t6, FRAME_T6(k1)
|
||||
sw t7, FRAME_T7(k1)
|
||||
mfc0 a1, MIPS_COP_0_CAUSE # 2nd arg is CAUSE
|
||||
mfc0 a2, MIPS_COP_0_CAUSE # 3rd arg is CAUSE
|
||||
sw s0, FRAME_S0(k1)
|
||||
sw s1, FRAME_S1(k1)
|
||||
sw s2, FRAME_S2(k1)
|
||||
sw s3, FRAME_S3(k1)
|
||||
mfc0 a2, MIPS_COP_0_EXC_PC # 3rd arg is PC
|
||||
mfc0 a3, MIPS_COP_0_EXC_PC # 4th arg is PC
|
||||
sw s4, FRAME_S4(k1)
|
||||
sw s5, FRAME_S5(k1)
|
||||
sw s6, FRAME_S6(k1)
|
||||
|
@ -430,24 +431,25 @@ NESTED_NOPROFILE(mips1_SystemCall, CALLFRAME_SIZ, ra)
|
|||
sw sp, FRAME_SP(k1)
|
||||
sw s8, FRAME_S8(k1)
|
||||
sw ra, FRAME_RA(k1)
|
||||
sw a0, FRAME_SR(k1)
|
||||
sw a1, FRAME_SR(k1)
|
||||
sw v0, FRAME_MULLO(k1)
|
||||
sw v1, FRAME_MULHI(k1)
|
||||
sw a2, FRAME_EPC(k1)
|
||||
sw a3, FRAME_EPC(k1)
|
||||
addu sp, k1, -CALLFRAME_SIZ # switch to kernel SP
|
||||
#ifdef __GP_SUPPORT__
|
||||
la gp, _C_LABEL(_gp) # switch to kernel GP
|
||||
#endif
|
||||
#if defined(DDB) || defined(DEBUG) || defined(KGDB)
|
||||
move ra, a2
|
||||
move ra, a3
|
||||
sw ra, CALLFRAME_RA(sp)
|
||||
#endif
|
||||
ori t0, a0, MIPS_SR_INT_IE # turn on IEc, enable intr.
|
||||
lw t1, P_MD_SYSCALL(a0) # t1 = syscall
|
||||
ori t0, a1, MIPS_SR_INT_IE # turn on IEc, enable intr.
|
||||
and t0, t0, ~MIPS_SR_COP_1_BIT # turn off FPU
|
||||
/*
|
||||
* Call the system call handler.
|
||||
*/
|
||||
jal _C_LABEL(syscall)
|
||||
jal t1
|
||||
mtc0 t0, MIPS_COP_0_STATUS
|
||||
/*
|
||||
* Check pending asynchronous traps.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: locore_mips3.S,v 1.64 2001/01/14 21:18:40 thorpej Exp $ */
|
||||
/* $NetBSD: locore_mips3.S,v 1.65 2001/01/16 06:01:26 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Jonathan Stone (hereinafter referred to as the author)
|
||||
|
@ -654,22 +654,23 @@ NESTED_NOPROFILE(mips3_SystemCall, CALLFRAME_SIZ, ra)
|
|||
REG_S a1, FRAME_A1(k1)
|
||||
REG_S a2, FRAME_A2(k1)
|
||||
REG_S a3, FRAME_A3(k1)
|
||||
lw a0, _C_LABEL(curproc) # 1st arg is curproc
|
||||
mfhi v1
|
||||
#REG_S t0, FRAME_T0(k1) # no need to save temp regs
|
||||
#REG_S t1, FRAME_T1(k1)
|
||||
#REG_S t2, FRAME_T2(k1)
|
||||
#REG_S t3, FRAME_T3(k1)
|
||||
mfc0 a0, MIPS_COP_0_STATUS # 1st arg is STATUS
|
||||
mfc0 a1, MIPS_COP_0_STATUS # 2nd arg is STATUS
|
||||
#REG_S t4, FRAME_T4(k1)
|
||||
#REG_S t5, FRAME_T5(k1)
|
||||
#REG_S t6, FRAME_T6(k1)
|
||||
#REG_S t7, FRAME_T7(k1)
|
||||
mfc0 a1, MIPS_COP_0_CAUSE # 2nd arg is CAUSE
|
||||
mfc0 a2, MIPS_COP_0_CAUSE # 3rd arg is CAUSE
|
||||
REG_S s0, FRAME_S0(k1)
|
||||
REG_S s1, FRAME_S1(k1)
|
||||
REG_S s2, FRAME_S2(k1)
|
||||
REG_S s3, FRAME_S3(k1)
|
||||
mfc0 a2, MIPS_COP_0_EXC_PC # 3rd arg is PC
|
||||
mfc0 a3, MIPS_COP_0_EXC_PC # 4th arg is PC
|
||||
REG_S s4, FRAME_S4(k1)
|
||||
REG_S s5, FRAME_S5(k1)
|
||||
REG_S s6, FRAME_S6(k1)
|
||||
|
@ -680,10 +681,10 @@ NESTED_NOPROFILE(mips3_SystemCall, CALLFRAME_SIZ, ra)
|
|||
REG_S sp, FRAME_SP(k1)
|
||||
REG_S s8, FRAME_S8(k1)
|
||||
REG_S ra, FRAME_RA(k1)
|
||||
REG_S a0, FRAME_SR(k1)
|
||||
REG_S a1, FRAME_SR(k1)
|
||||
REG_S v0, FRAME_MULLO(k1)
|
||||
REG_S v1, FRAME_MULHI(k1)
|
||||
REG_S a2, FRAME_EPC(k1)
|
||||
REG_S a3, FRAME_EPC(k1)
|
||||
addu sp, k1, -CALLFRAME_SIZ
|
||||
#ifdef __GP_SUPPORT__
|
||||
la gp, _C_LABEL(_gp) # switch to kernel GP
|
||||
|
@ -692,17 +693,18 @@ NESTED_NOPROFILE(mips3_SystemCall, CALLFRAME_SIZ, ra)
|
|||
* Turn off fpu and enter kernel mode
|
||||
*/
|
||||
.set at
|
||||
and t0, a0, ~(MIPS_SR_COP_1_BIT | MIPS_SR_EXL | MIPS_SR_KSU_MASK)
|
||||
lw t1, P_MD_SYSCALL(a0) # t1 = syscall
|
||||
and t0, a1, ~(MIPS_SR_COP_1_BIT | MIPS_SR_EXL | MIPS_SR_KSU_MASK)
|
||||
.set noat
|
||||
#if defined(DDB) || defined(DEBUG) || defined(KGDB)
|
||||
move ra, a2
|
||||
move ra, a3
|
||||
sw ra, CALLFRAME_RA(sp)
|
||||
#endif
|
||||
/*
|
||||
* Call the system call handler.
|
||||
*/
|
||||
mtc0 t0, MIPS_COP_0_STATUS # re-enable interrupts
|
||||
jal _C_LABEL(syscall)
|
||||
jal t1
|
||||
nop
|
||||
/*
|
||||
* Check pending asynchronous traps.
|
||||
|
|
|
@ -0,0 +1,381 @@
|
|||
/* $NetBSD: syscall.c,v 1.1 2001/01/16 06:01:27 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe and by Charles M. Hannum.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988 University of Utah.
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Systems Programming Group of the University of Utah Computer
|
||||
* Science Department and Ralph Campbell.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: Utah Hdr: trap.c 1.32 91/04/06
|
||||
*
|
||||
* @(#)trap.c 8.5 (Berkeley) 1/11/94
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
|
||||
|
||||
__KERNEL_RCSID(0, "$NetBSD: syscall.c,v 1.1 2001/01/16 06:01:27 thorpej Exp $");
|
||||
|
||||
#include "opt_ktrace.h"
|
||||
#include "opt_syscall_debug.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/signal.h>
|
||||
#ifdef KTRACE
|
||||
#include <sys/ktrace.h>
|
||||
#endif
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#include <uvm/uvm_extern.h>
|
||||
|
||||
#include <machine/cpu.h>
|
||||
#include <mips/trap.h>
|
||||
#include <mips/reg.h>
|
||||
#include <mips/regnum.h> /* symbolic register indices */
|
||||
#include <mips/userret.h>
|
||||
|
||||
void syscall_intern(struct proc *);
|
||||
void syscall_plain(struct proc *, u_int, u_int, u_int);
|
||||
void syscall_fancy(struct proc *, u_int, u_int, u_int);
|
||||
|
||||
vaddr_t MachEmulateBranch(struct frame *, vaddr_t, u_int, int);
|
||||
|
||||
#define DELAYBRANCH(x) ((int)(x)<0)
|
||||
|
||||
void
|
||||
syscall_intern(struct proc *p)
|
||||
{
|
||||
|
||||
#ifdef KTRACE
|
||||
if (p->p_traceflag & (KTRFAC_SYSCALL | KTRFAC_SYSRET))
|
||||
p->p_md.md_syscall = syscall_fancy;
|
||||
else
|
||||
#endif
|
||||
p->p_md.md_syscall = syscall_plain;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a system call.
|
||||
*
|
||||
* System calls are strange beasts. They are passed the syscall number
|
||||
* in v0, and the arguments in the registers (as normal). They return
|
||||
* an error flag in a3 (if a3 != 0 on return, the syscall had an error),
|
||||
* and the return value (if any) in v0 and possibly v1.
|
||||
*
|
||||
* XXX Needs to be heavily rototilled for N32 or LP64 support.
|
||||
*/
|
||||
|
||||
void
|
||||
syscall_plain(struct proc *p, u_int status, u_int cause, u_int opc)
|
||||
{
|
||||
struct frame *frame = (struct frame *)p->p_md.md_regs;
|
||||
mips_reg_t *args, copyargs[8];
|
||||
size_t code, numsys, nsaved, nargs;
|
||||
const struct sysent *callp;
|
||||
int error;
|
||||
|
||||
uvmexp.syscalls++;
|
||||
|
||||
if (DELAYBRANCH(cause))
|
||||
frame->f_regs[PC] = MachEmulateBranch(frame, opc, 0, 0);
|
||||
else
|
||||
frame->f_regs[PC] = opc + sizeof(int);
|
||||
|
||||
callp = p->p_emul->e_sysent;
|
||||
numsys = p->p_emul->e_nsysent;
|
||||
code = frame->f_regs[V0];
|
||||
|
||||
switch (code) {
|
||||
case SYS_syscall:
|
||||
case SYS___syscall:
|
||||
args = copyargs;
|
||||
if (code == SYS_syscall) {
|
||||
/*
|
||||
* Code is first argument, followed by actual args.
|
||||
*/
|
||||
code = frame->f_regs[A0];
|
||||
args[0] = frame->f_regs[A1];
|
||||
args[1] = frame->f_regs[A2];
|
||||
args[2] = frame->f_regs[A3];
|
||||
nsaved = 3;
|
||||
} else {
|
||||
/*
|
||||
* Like syscall, but code is a quad, so as to maintain
|
||||
* quad alignment for the rest of the arguments.
|
||||
*/
|
||||
code = frame->f_regs[A0 + _QUAD_LOWWORD];
|
||||
args[0] = frame->f_regs[A2];
|
||||
args[1] = frame->f_regs[A3];
|
||||
nsaved = 2;
|
||||
}
|
||||
|
||||
if (code >= p->p_emul->e_nsysent)
|
||||
callp += p->p_emul->e_nosys;
|
||||
else
|
||||
callp += code;
|
||||
nargs = callp->sy_argsize / sizeof(mips_reg_t);
|
||||
|
||||
if (nargs > nsaved) {
|
||||
error = copyin(
|
||||
((mips_reg_t *)(vaddr_t)frame->f_regs[SP] + 4),
|
||||
(args + nsaved),
|
||||
(nargs - nsaved) * sizeof(mips_reg_t));
|
||||
if (error)
|
||||
goto bad;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (code >= p->p_emul->e_nsysent)
|
||||
callp += p->p_emul->e_nosys;
|
||||
else
|
||||
callp += code;
|
||||
nargs = callp->sy_narg;
|
||||
|
||||
if (nargs < 5)
|
||||
args = &frame->f_regs[A0];
|
||||
else {
|
||||
args = copyargs;
|
||||
error = copyin(
|
||||
((mips_reg_t *)(vaddr_t)frame->f_regs[SP] + 4),
|
||||
(©args[4]),
|
||||
(nargs - 4) * sizeof(mips_reg_t));
|
||||
if (error)
|
||||
goto bad;
|
||||
args[0] = frame->f_regs[A0];
|
||||
args[1] = frame->f_regs[A1];
|
||||
args[2] = frame->f_regs[A2];
|
||||
args[3] = frame->f_regs[A3];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef SYSCALL_DEBUG
|
||||
scdebug_call(p, code, args);
|
||||
#endif
|
||||
|
||||
frame->f_regs[V0] = 0;
|
||||
|
||||
/* XXX register_t vs. mips_reg_t */
|
||||
error = (*callp->sy_call)(p, args, (register_t *)&frame->f_regs[V0]);
|
||||
|
||||
switch (error) {
|
||||
case 0:
|
||||
frame->f_regs[A3] = 0;
|
||||
break;
|
||||
case ERESTART:
|
||||
frame->f_regs[PC] = opc;
|
||||
break;
|
||||
case EJUSTRETURN:
|
||||
break; /* nothing to do */
|
||||
default:
|
||||
bad:
|
||||
frame->f_regs[V0] = error;
|
||||
frame->f_regs[A3] = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef SYSCALL_DEBUG
|
||||
scdebug_ret(p, code, error, rval);
|
||||
#endif
|
||||
|
||||
userret(p);
|
||||
}
|
||||
|
||||
void
|
||||
syscall_fancy(struct proc *p, u_int status, u_int cause, u_int opc)
|
||||
{
|
||||
struct frame *frame = (struct frame *)p->p_md.md_regs;
|
||||
mips_reg_t *args, copyargs[8];
|
||||
size_t code, numsys, nsaved, nargs;
|
||||
const struct sysent *callp;
|
||||
int error;
|
||||
|
||||
uvmexp.syscalls++;
|
||||
|
||||
if (DELAYBRANCH(cause))
|
||||
frame->f_regs[PC] = MachEmulateBranch(frame, opc, 0, 0);
|
||||
else
|
||||
frame->f_regs[PC] = opc + sizeof(int);
|
||||
|
||||
callp = p->p_emul->e_sysent;
|
||||
numsys = p->p_emul->e_nsysent;
|
||||
code = frame->f_regs[V0];
|
||||
|
||||
switch (code) {
|
||||
case SYS_syscall:
|
||||
case SYS___syscall:
|
||||
args = copyargs;
|
||||
if (code == SYS_syscall) {
|
||||
/*
|
||||
* Code is first argument, followed by actual args.
|
||||
*/
|
||||
code = frame->f_regs[A0];
|
||||
args[0] = frame->f_regs[A1];
|
||||
args[1] = frame->f_regs[A2];
|
||||
args[2] = frame->f_regs[A3];
|
||||
nsaved = 3;
|
||||
} else {
|
||||
/*
|
||||
* Like syscall, but code is a quad, so as to maintain
|
||||
* quad alignment for the rest of the arguments.
|
||||
*/
|
||||
code = frame->f_regs[A0 + _QUAD_LOWWORD];
|
||||
args[0] = frame->f_regs[A2];
|
||||
args[1] = frame->f_regs[A3];
|
||||
nsaved = 2;
|
||||
}
|
||||
|
||||
if (code >= p->p_emul->e_nsysent)
|
||||
callp += p->p_emul->e_nosys;
|
||||
else
|
||||
callp += code;
|
||||
nargs = callp->sy_argsize / sizeof(mips_reg_t);
|
||||
|
||||
if (nargs > nsaved) {
|
||||
error = copyin(
|
||||
((mips_reg_t *)(vaddr_t)frame->f_regs[SP] + 4),
|
||||
(args + nsaved),
|
||||
(nargs - nsaved) * sizeof(mips_reg_t));
|
||||
if (error)
|
||||
goto bad;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (code >= p->p_emul->e_nsysent)
|
||||
callp += p->p_emul->e_nosys;
|
||||
else
|
||||
callp += code;
|
||||
nargs = callp->sy_narg;
|
||||
|
||||
if (nargs < 5)
|
||||
args = &frame->f_regs[A0];
|
||||
else {
|
||||
args = copyargs;
|
||||
error = copyin(
|
||||
((mips_reg_t *)(vaddr_t)frame->f_regs[SP] + 4),
|
||||
(©args[4]),
|
||||
(nargs - 4) * sizeof(mips_reg_t));
|
||||
if (error)
|
||||
goto bad;
|
||||
args[0] = frame->f_regs[A0];
|
||||
args[1] = frame->f_regs[A1];
|
||||
args[2] = frame->f_regs[A2];
|
||||
args[3] = frame->f_regs[A3];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef SYSCALL_DEBUG
|
||||
scdebug_call(p, code, args);
|
||||
#endif
|
||||
|
||||
#ifdef KTRACE
|
||||
if (KTRPOINT(p, KTR_SYSCALL)) {
|
||||
/* XXX register_t vs. mips_reg_t */
|
||||
ktrsyscall(p, code, callp->sy_argsize, (register_t *)args);
|
||||
}
|
||||
#endif
|
||||
|
||||
frame->f_regs[V0] = 0;
|
||||
|
||||
/* XXX register_t vs. mips_reg_t */
|
||||
error = (*callp->sy_call)(p, args, (register_t *)&frame->f_regs[V0]);
|
||||
|
||||
switch (error) {
|
||||
case 0:
|
||||
frame->f_regs[A3] = 0;
|
||||
break;
|
||||
case ERESTART:
|
||||
frame->f_regs[PC] = opc;
|
||||
break;
|
||||
case EJUSTRETURN:
|
||||
break; /* nothing to do */
|
||||
default:
|
||||
bad:
|
||||
frame->f_regs[V0] = error;
|
||||
frame->f_regs[A3] = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef SYSCALL_DEBUG
|
||||
scdebug_ret(p, code, error, rval);
|
||||
#endif
|
||||
|
||||
userret(p);
|
||||
|
||||
#ifdef KTRACE
|
||||
if (KTRPOINT(p, KTR_SYSRET))
|
||||
ktrsysret(p, code, error, frame->f_regs[V0]);
|
||||
#endif
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: trap.c,v 1.159 2001/01/14 21:22:57 thorpej Exp $ */
|
||||
/* $NetBSD: trap.c,v 1.160 2001/01/16 06:01:27 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988 University of Utah.
|
||||
|
@ -44,12 +44,11 @@
|
|||
|
||||
#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
|
||||
|
||||
__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.159 2001/01/14 21:22:57 thorpej Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.160 2001/01/16 06:01:27 thorpej Exp $");
|
||||
|
||||
#include "opt_cputype.h" /* which mips CPU levels do we support? */
|
||||
#include "opt_ktrace.h"
|
||||
#include "opt_ddb.h"
|
||||
#include "opt_syscall_debug.h"
|
||||
|
||||
#if !defined(MIPS1) && !defined(MIPS3)
|
||||
#error Neither "MIPS1" (r2000 family), "MIPS3" (r4000 family) was configured.
|
||||
|
@ -129,7 +128,6 @@ const char *trap_type[] = {
|
|||
};
|
||||
|
||||
void trap __P((unsigned, unsigned, unsigned, unsigned, struct trapframe *));
|
||||
void syscall __P((unsigned, unsigned, unsigned));
|
||||
void ast __P((unsigned));
|
||||
|
||||
vaddr_t MachEmulateBranch __P((struct frame *, vaddr_t, unsigned, int));
|
||||
|
@ -137,120 +135,6 @@ extern void MachEmulateFP __P((unsigned));
|
|||
extern void MachFPInterrupt __P((unsigned, unsigned, unsigned, struct frame *));
|
||||
|
||||
#define DELAYBRANCH(x) ((int)(x)<0)
|
||||
/*
|
||||
* Process a system call.
|
||||
*
|
||||
* System calls are strange beasts. They are passed the syscall number
|
||||
* in v0, and the arguments in the registers (as normal). They return
|
||||
* an error flag in a3 (if a3 != 0 on return, the syscall had an error),
|
||||
* and the return value (if any) in v0 and possibly v1.
|
||||
*/
|
||||
void
|
||||
syscall(status, cause, opc)
|
||||
unsigned status;
|
||||
unsigned cause;
|
||||
unsigned opc;
|
||||
{
|
||||
struct proc *p = curproc;
|
||||
struct frame *frame = (struct frame *)p->p_md.md_regs;
|
||||
int args[8], rval[2], error;
|
||||
size_t code, numsys, nsaved, argsiz;
|
||||
const struct sysent *callp;
|
||||
|
||||
uvmexp.syscalls++;
|
||||
|
||||
if (DELAYBRANCH(cause))
|
||||
frame->f_regs[PC] = MachEmulateBranch(frame, opc, 0, 0);
|
||||
else
|
||||
frame->f_regs[PC] = opc + sizeof(int);
|
||||
callp = p->p_emul->e_sysent;
|
||||
numsys = p->p_emul->e_nsysent;
|
||||
code = frame->f_regs[V0];
|
||||
switch (code) {
|
||||
case SYS_syscall:
|
||||
/*
|
||||
* Code is first argument, followed by actual args.
|
||||
*/
|
||||
code = frame->f_regs[A0];
|
||||
args[0] = frame->f_regs[A1];
|
||||
args[1] = frame->f_regs[A2];
|
||||
args[2] = frame->f_regs[A3];
|
||||
nsaved = 3;
|
||||
break;
|
||||
case SYS___syscall:
|
||||
/*
|
||||
* Like syscall, but code is a quad, so as to maintain
|
||||
* quad alignment for the rest of the arguments.
|
||||
*/
|
||||
code = frame->f_regs[A0 + _QUAD_LOWWORD];
|
||||
args[0] = frame->f_regs[A2];
|
||||
args[1] = frame->f_regs[A3];
|
||||
nsaved = 2;
|
||||
break;
|
||||
default:
|
||||
args[0] = frame->f_regs[A0];
|
||||
args[1] = frame->f_regs[A1];
|
||||
args[2] = frame->f_regs[A2];
|
||||
args[3] = frame->f_regs[A3];
|
||||
nsaved = 4;
|
||||
break;
|
||||
}
|
||||
if (code >= p->p_emul->e_nsysent)
|
||||
callp += p->p_emul->e_nosys;
|
||||
else
|
||||
callp += code;
|
||||
argsiz = callp->sy_argsize / sizeof(int);
|
||||
if (argsiz > nsaved) {
|
||||
error = copyin(
|
||||
(void *)((int *)(vaddr_t)frame->f_regs[SP] + 4),
|
||||
(void *)(args + nsaved),
|
||||
(argsiz - nsaved) * sizeof(int));
|
||||
if (error)
|
||||
goto bad;
|
||||
}
|
||||
#ifdef SYSCALL_DEBUG
|
||||
scdebug_call(p, code, args);
|
||||
#endif
|
||||
#ifdef KTRACE
|
||||
if (KTRPOINT(p, KTR_SYSCALL))
|
||||
ktrsyscall(p, code, callp->sy_argsize, args);
|
||||
#endif
|
||||
rval[0] = 0;
|
||||
rval[1] = frame->f_regs[V1];
|
||||
#ifdef DEBUG
|
||||
/* XXX save code */
|
||||
#endif
|
||||
error = (*callp->sy_call)(p, args, rval);
|
||||
|
||||
#ifdef DEBUG
|
||||
/* XXX save syscall result in trapdebug */
|
||||
#endif
|
||||
switch (error) {
|
||||
case 0:
|
||||
frame->f_regs[V0] = rval[0];
|
||||
frame->f_regs[V1] = rval[1];
|
||||
frame->f_regs[A3] = 0;
|
||||
break;
|
||||
case ERESTART:
|
||||
frame->f_regs[PC] = opc;
|
||||
break;
|
||||
case EJUSTRETURN:
|
||||
break; /* nothing to do */
|
||||
default:
|
||||
bad:
|
||||
frame->f_regs[V0] = error;
|
||||
frame->f_regs[A3] = 1;
|
||||
break;
|
||||
}
|
||||
#ifdef SYSCALL_DEBUG
|
||||
scdebug_ret(p, code, error, rval);
|
||||
#endif
|
||||
userret(p);
|
||||
#ifdef KTRACE
|
||||
if (KTRPOINT(p, KTR_SYSRET))
|
||||
ktrsysret(p, code, error, rval[0]);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* fork syscall returns directly to user process via proc_trampoline,
|
||||
|
|
Loading…
Reference in New Issue