From 51d0cd96db64016ed76a86e3c23efc1cc57e451b Mon Sep 17 00:00:00 2001 From: uwe Date: Sun, 10 Jul 2005 22:27:20 +0000 Subject: [PATCH] Implement syscall_intern for sh3. --- sys/arch/sh3/conf/files.sh3 | 3 +- sys/arch/sh3/include/proc.h | 4 +- sys/arch/sh3/include/types.h | 3 +- sys/arch/sh3/sh3/exception.c | 147 +------------ sys/arch/sh3/sh3/syscall.c | 402 +++++++++++++++++++++++++++++++++++ 5 files changed, 412 insertions(+), 147 deletions(-) create mode 100644 sys/arch/sh3/sh3/syscall.c diff --git a/sys/arch/sh3/conf/files.sh3 b/sys/arch/sh3/conf/files.sh3 index db701f273dfe..0d14678a2702 100644 --- a/sys/arch/sh3/conf/files.sh3 +++ b/sys/arch/sh3/conf/files.sh3 @@ -1,4 +1,4 @@ -# $NetBSD: files.sh3,v 1.30 2003/07/27 01:19:31 thorpej Exp $ +# $NetBSD: files.sh3,v 1.31 2005/07/10 22:27:20 uwe Exp $ # defflag opt_cputype.h SH3 SH4 @@ -23,6 +23,7 @@ file arch/sh3/sh3/pmap.c file arch/sh3/sh3/process_machdep.c file arch/sh3/sh3/sh3_machdep.c file arch/sh3/sh3/sys_machdep.c +file arch/sh3/sh3/syscall.c file arch/sh3/sh3/vm_machdep.c file arch/sh3/sh3/cache.c file arch/sh3/sh3/cache_sh3.c sh3 diff --git a/sys/arch/sh3/include/proc.h b/sys/arch/sh3/include/proc.h index 55ea8cd553b8..f26e98ba117b 100644 --- a/sys/arch/sh3/include/proc.h +++ b/sys/arch/sh3/include/proc.h @@ -1,4 +1,4 @@ -/* $NetBSD: proc.h,v 1.8 2005/07/10 16:21:01 uwe Exp $ */ +/* $NetBSD: proc.h,v 1.9 2005/07/10 22:27:20 uwe Exp $ */ /* * Copyright (c) 2002 The NetBSD Foundation, Inc. All rights reserved. @@ -59,6 +59,8 @@ struct mdlwp { #define MDP_USEDFPU 0x0001 /* has used the FPU */ struct mdproc { + void (*md_syscall)(struct lwp *, struct trapframe *); + volatile int md_astpending; /* AST pending on return to userland */ }; diff --git a/sys/arch/sh3/include/types.h b/sys/arch/sh3/include/types.h index 9d63138b339a..48fedf60276f 100644 --- a/sys/arch/sh3/include/types.h +++ b/sys/arch/sh3/include/types.h @@ -1,4 +1,4 @@ -/* $NetBSD: types.h,v 1.20 2005/07/10 16:24:29 uwe Exp $ */ +/* $NetBSD: types.h,v 1.21 2005/07/10 22:27:20 uwe Exp $ */ /*- * Copyright (c) 1990 The Regents of the University of California. @@ -66,6 +66,7 @@ typedef volatile unsigned char __cpu_simple_lock_t; #define __HAVE_AST_PERPROC #define __HAVE_GENERIC_SOFT_INTERRUPTS +#define __HAVE_SYSCALL_INTERN #if defined(_KERNEL) #define __HAVE_RAS diff --git a/sys/arch/sh3/sh3/exception.c b/sys/arch/sh3/sh3/exception.c index 6925fdd79706..5a44c9c1eb05 100644 --- a/sys/arch/sh3/sh3/exception.c +++ b/sys/arch/sh3/sh3/exception.c @@ -1,4 +1,4 @@ -/* $NetBSD: exception.c,v 1.21 2005/07/01 18:01:45 christos Exp $ */ +/* $NetBSD: exception.c,v 1.22 2005/07/10 22:27:20 uwe Exp $ */ /*- * Copyright (c) 2002 The NetBSD Foundation, Inc. All rights reserved. @@ -79,7 +79,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: exception.c,v 1.21 2005/07/01 18:01:45 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: exception.c,v 1.22 2005/07/10 22:27:20 uwe Exp $"); #include "opt_ddb.h" #include "opt_kgdb.h" @@ -140,7 +140,6 @@ const int exp_types = sizeof exp_type / sizeof exp_type[0]; void general_exception(struct lwp *, struct trapframe *, uint32_t); void tlb_exception(struct lwp *, struct trapframe *, uint32_t); -void syscall(struct lwp *, struct trapframe *); void ast(struct lwp *, struct trapframe *); /* @@ -177,7 +176,7 @@ general_exception(struct lwp *l, struct trapframe *tf, uint32_t va) ksi.ksi_addr = (void *)tf->tf_spc; goto trapsignal; } else { - syscall(l, tf); + (*l->l_proc->p_md.md_syscall)(l, tf); return; } break; @@ -259,146 +258,6 @@ general_exception(struct lwp *l, struct trapframe *tf, uint32_t va) /*NOTREACHED*/ } -/* - * void syscall(struct lwp *l, struct trapframe *tf): - * l ... curlwp when exception occur. - * tf ... full user context. - * System call request from POSIX system call gate interface to kernel. - */ -void -syscall(struct lwp *l, struct trapframe *tf) -{ - struct proc *p = l->l_proc; - caddr_t params; - const struct sysent *callp; - int error, opc, nsys; - size_t argsize; - register_t code, args[8], rval[2], ocode; - - uvmexp.syscalls++; - - opc = tf->tf_spc; - ocode = code = tf->tf_r0; - - nsys = p->p_emul->e_nsysent; - callp = p->p_emul->e_sysent; - - params = (caddr_t)tf->tf_r15; - - switch (code) { - case SYS_syscall: - /* - * Code is first argument, followed by actual args. - */ - code = tf->tf_r4; /* fuword(params); */ - /* params += sizeof(int); */ - break; - case SYS___syscall: - /* - * Like syscall, but code is a quad, so as to maintain - * quad alignment for the rest of the arguments. - */ - if (callp != sysent) - break; - /* fuword(params + _QUAD_LOWWORD * sizeof(int)); */ -#if _BYTE_ORDER == BIG_ENDIAN - code = tf->tf_r5; -#else - code = tf->tf_r4; -#endif - /* params += sizeof(quad_t); */ - break; - default: - break; - } - if (code < 0 || code >= nsys) - callp += p->p_emul->e_nosys; /* illegal */ - else - callp += code; - argsize = callp->sy_argsize; - - if (ocode == SYS_syscall) { - if (argsize) { - args[0] = tf->tf_r5; - args[1] = tf->tf_r6; - args[2] = tf->tf_r7; - if (argsize > 3 * sizeof(int)) { - argsize -= 3 * sizeof(int); - error = copyin(params, (caddr_t)&args[3], - argsize); - } else - error = 0; - } else - error = 0; - } - else if (ocode == SYS___syscall) { - if (argsize) { - args[0] = tf->tf_r6; - args[1] = tf->tf_r7; - if (argsize > 2 * sizeof(int)) { - argsize -= 2 * sizeof(int); - error = copyin(params, (caddr_t)&args[2], - argsize); - } else - error = 0; - } else - error = 0; - } else { - if (argsize) { - args[0] = tf->tf_r4; - args[1] = tf->tf_r5; - args[2] = tf->tf_r6; - args[3] = tf->tf_r7; - if (argsize > 4 * sizeof(int)) { - argsize -= 4 * sizeof(int); - error = copyin(params, (caddr_t)&args[4], - argsize); - } else - error = 0; - } else - error = 0; - } - - if (error) - goto bad; - - if ((error = trace_enter(l, code, code, NULL, args)) != 0) - goto out; - - rval[0] = 0; - rval[1] = tf->tf_r1; - error = (*callp->sy_call)(l, args, rval); -out: - switch (error) { - case 0: - tf->tf_r0 = rval[0]; - tf->tf_r1 = rval[1]; - tf->tf_ssr |= PSL_TBIT; /* T bit */ - - break; - case ERESTART: - /* 2 = TRAPA instruction size */ - tf->tf_spc = opc - 2; - - break; - case EJUSTRETURN: - /* nothing to do */ - break; - default: - bad: - if (p->p_emul->e_errno) - error = p->p_emul->e_errno[error]; - tf->tf_r0 = error; - tf->tf_ssr &= ~PSL_TBIT; /* T bit */ - - break; - } - - - trace_exit(l, code, args, rval, error); - - userret(l); -} /* * void tlb_exception(struct lwp *l, struct trapframe *tf, uint32_t va): diff --git a/sys/arch/sh3/sh3/syscall.c b/sys/arch/sh3/sh3/syscall.c new file mode 100644 index 000000000000..92e75bc7c656 --- /dev/null +++ b/sys/arch/sh3/sh3/syscall.c @@ -0,0 +1,402 @@ +/* $NetBSD: syscall.c,v 1.1 2005/07/10 22:27:20 uwe Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. All rights reserved. + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the University of Utah, and William Jolitz. + * + * 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. 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. + * + * @(#)trap.c 7.4 (Berkeley) 5/13/91 + */ + +/*- + * Copyright (c) 1995 Charles M. Hannum. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the University of Utah, and William Jolitz. + * + * 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. + * + * @(#)trap.c 7.4 (Berkeley) 5/13/91 + */ + +/* + * SH3 Trap and System call handling + * + * T.Horiuchi 1998.06.8 + */ + +#include "opt_ktrace.h" +#include "opt_syscall_debug.h" +#include "opt_systrace.h" + +#include +#include +#include +#include +#include +#ifdef KTRACE +#include +#endif +#ifdef SYSTRACE +#include +#endif +#include + +#include + +#include + + +static void syscall_plain(struct lwp *, struct trapframe *); +#if defined(KTRACE) || defined(SYSTRACE) +static void syscall_fancy(struct lwp *, struct trapframe *); +#endif + + +void +syscall_intern(struct proc *p) +{ + +#ifdef KTRACE + if (p->p_traceflag & (KTRFAC_SYSCALL | KTRFAC_SYSRET)) { + p->p_md.md_syscall = syscall_fancy; + return; + } +#endif +#ifdef SYSTRACE + if (ISSET(p->p_flag, P_SYSTRACE)) { + p->p_md.md_syscall = syscall_fancy; + return; + } +#endif + p->p_md.md_syscall = syscall_plain; +} + + +/* + * System call request from POSIX system call gate interface to kernel. + * l ... curlwp when trap occurs. + * tf ... full user context. + */ +static void +syscall_plain(struct lwp *l, struct trapframe *tf) +{ + struct proc *p = l->l_proc; + caddr_t params; + const struct sysent *callp; + int error, opc, nsys; + size_t argsize; + register_t code, args[8], rval[2], ocode; + + uvmexp.syscalls++; + + opc = tf->tf_spc; + ocode = code = tf->tf_r0; + + nsys = p->p_emul->e_nsysent; + callp = p->p_emul->e_sysent; + + params = (caddr_t)tf->tf_r15; + + switch (code) { + case SYS_syscall: + /* + * Code is first argument, followed by actual args. + */ + code = tf->tf_r4; /* fuword(params); */ + /* params += sizeof(int); */ + break; + case SYS___syscall: + /* + * Like syscall, but code is a quad, so as to maintain + * quad alignment for the rest of the arguments. + */ + if (callp != sysent) + break; + /* fuword(params + _QUAD_LOWWORD * sizeof(int)); */ +#if _BYTE_ORDER == BIG_ENDIAN + code = tf->tf_r5; +#else + code = tf->tf_r4; +#endif + /* params += sizeof(quad_t); */ + break; + default: + break; + } + if (code < 0 || code >= nsys) + callp += p->p_emul->e_nosys; /* illegal */ + else + callp += code; + argsize = callp->sy_argsize; + + if (ocode == SYS_syscall) { + if (argsize) { + args[0] = tf->tf_r5; + args[1] = tf->tf_r6; + args[2] = tf->tf_r7; + if (argsize > 3 * sizeof(int)) { + argsize -= 3 * sizeof(int); + error = copyin(params, (caddr_t)&args[3], + argsize); + } else + error = 0; + } else + error = 0; + } + else if (ocode == SYS___syscall) { + if (argsize) { + args[0] = tf->tf_r6; + args[1] = tf->tf_r7; + if (argsize > 2 * sizeof(int)) { + argsize -= 2 * sizeof(int); + error = copyin(params, (caddr_t)&args[2], + argsize); + } else + error = 0; + } else + error = 0; + } else { + if (argsize) { + args[0] = tf->tf_r4; + args[1] = tf->tf_r5; + args[2] = tf->tf_r6; + args[3] = tf->tf_r7; + if (argsize > 4 * sizeof(int)) { + argsize -= 4 * sizeof(int); + error = copyin(params, (caddr_t)&args[4], + argsize); + } else + error = 0; + } else + error = 0; + } + + if (error) + goto bad; + + rval[0] = 0; + rval[1] = tf->tf_r1; + error = (*callp->sy_call)(l, args, rval); + + switch (error) { + case 0: + tf->tf_r0 = rval[0]; + tf->tf_r1 = rval[1]; + tf->tf_ssr |= PSL_TBIT; /* T bit */ + + break; + case ERESTART: + /* 2 = TRAPA instruction size */ + tf->tf_spc = opc - 2; + + break; + case EJUSTRETURN: + /* nothing to do */ + break; + default: + bad: + if (p->p_emul->e_errno) + error = p->p_emul->e_errno[error]; + tf->tf_r0 = error; + tf->tf_ssr &= ~PSL_TBIT; /* T bit */ + + break; + } + + userret(l); +} + + +#if defined(KTRACE) || defined(SYSTRACE) +/* + * Like syscall_plain but with trace_enter/trace_exit. + */ +static void +syscall_fancy(struct lwp *l, struct trapframe *tf) +{ + struct proc *p = l->l_proc; + caddr_t params; + const struct sysent *callp; + int error, opc, nsys; + size_t argsize; + register_t code, args[8], rval[2], ocode; + + uvmexp.syscalls++; + + opc = tf->tf_spc; + ocode = code = tf->tf_r0; + + nsys = p->p_emul->e_nsysent; + callp = p->p_emul->e_sysent; + + params = (caddr_t)tf->tf_r15; + + switch (code) { + case SYS_syscall: + /* + * Code is first argument, followed by actual args. + */ + code = tf->tf_r4; /* fuword(params); */ + /* params += sizeof(int); */ + break; + case SYS___syscall: + /* + * Like syscall, but code is a quad, so as to maintain + * quad alignment for the rest of the arguments. + */ + if (callp != sysent) + break; + /* fuword(params + _QUAD_LOWWORD * sizeof(int)); */ +#if _BYTE_ORDER == BIG_ENDIAN + code = tf->tf_r5; +#else + code = tf->tf_r4; +#endif + /* params += sizeof(quad_t); */ + break; + default: + break; + } + if (code < 0 || code >= nsys) + callp += p->p_emul->e_nosys; /* illegal */ + else + callp += code; + argsize = callp->sy_argsize; + + if (ocode == SYS_syscall) { + if (argsize) { + args[0] = tf->tf_r5; + args[1] = tf->tf_r6; + args[2] = tf->tf_r7; + if (argsize > 3 * sizeof(int)) { + argsize -= 3 * sizeof(int); + error = copyin(params, (caddr_t)&args[3], + argsize); + } else + error = 0; + } else + error = 0; + } + else if (ocode == SYS___syscall) { + if (argsize) { + args[0] = tf->tf_r6; + args[1] = tf->tf_r7; + if (argsize > 2 * sizeof(int)) { + argsize -= 2 * sizeof(int); + error = copyin(params, (caddr_t)&args[2], + argsize); + } else + error = 0; + } else + error = 0; + } else { + if (argsize) { + args[0] = tf->tf_r4; + args[1] = tf->tf_r5; + args[2] = tf->tf_r6; + args[3] = tf->tf_r7; + if (argsize > 4 * sizeof(int)) { + argsize -= 4 * sizeof(int); + error = copyin(params, (caddr_t)&args[4], + argsize); + } else + error = 0; + } else + error = 0; + } + + if (error) + goto bad; + + if ((error = trace_enter(l, code, code, NULL, args)) != 0) + goto out; + + rval[0] = 0; + rval[1] = tf->tf_r1; + error = (*callp->sy_call)(l, args, rval); +out: + switch (error) { + case 0: + tf->tf_r0 = rval[0]; + tf->tf_r1 = rval[1]; + tf->tf_ssr |= PSL_TBIT; /* T bit */ + + break; + case ERESTART: + /* 2 = TRAPA instruction size */ + tf->tf_spc = opc - 2; + + break; + case EJUSTRETURN: + /* nothing to do */ + break; + default: + bad: + if (p->p_emul->e_errno) + error = p->p_emul->e_errno[error]; + tf->tf_r0 = error; + tf->tf_ssr &= ~PSL_TBIT; /* T bit */ + + break; + } + + + trace_exit(l, code, args, rval, error); + + userret(l); +} +#endif /* KTRACE || SYSTRACE */