Implement syscall_intern for sh3.

This commit is contained in:
uwe 2005-07-10 22:27:20 +00:00
parent f5546fc71e
commit 51d0cd96db
5 changed files with 412 additions and 147 deletions

View File

@ -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 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/process_machdep.c
file arch/sh3/sh3/sh3_machdep.c file arch/sh3/sh3/sh3_machdep.c
file arch/sh3/sh3/sys_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/vm_machdep.c
file arch/sh3/sh3/cache.c file arch/sh3/sh3/cache.c
file arch/sh3/sh3/cache_sh3.c sh3 file arch/sh3/sh3/cache_sh3.c sh3

View File

@ -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. * Copyright (c) 2002 The NetBSD Foundation, Inc. All rights reserved.
@ -59,6 +59,8 @@ struct mdlwp {
#define MDP_USEDFPU 0x0001 /* has used the FPU */ #define MDP_USEDFPU 0x0001 /* has used the FPU */
struct mdproc { struct mdproc {
void (*md_syscall)(struct lwp *, struct trapframe *);
volatile int md_astpending; /* AST pending on return to userland */ volatile int md_astpending; /* AST pending on return to userland */
}; };

View File

@ -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. * 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_AST_PERPROC
#define __HAVE_GENERIC_SOFT_INTERRUPTS #define __HAVE_GENERIC_SOFT_INTERRUPTS
#define __HAVE_SYSCALL_INTERN
#if defined(_KERNEL) #if defined(_KERNEL)
#define __HAVE_RAS #define __HAVE_RAS

View File

@ -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. * Copyright (c) 2002 The NetBSD Foundation, Inc. All rights reserved.
@ -79,7 +79,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__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_ddb.h"
#include "opt_kgdb.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 general_exception(struct lwp *, struct trapframe *, uint32_t);
void tlb_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 *); 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; ksi.ksi_addr = (void *)tf->tf_spc;
goto trapsignal; goto trapsignal;
} else { } else {
syscall(l, tf); (*l->l_proc->p_md.md_syscall)(l, tf);
return; return;
} }
break; break;
@ -259,146 +258,6 @@ general_exception(struct lwp *l, struct trapframe *tf, uint32_t va)
/*NOTREACHED*/ /*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): * void tlb_exception(struct lwp *l, struct trapframe *tf, uint32_t va):

402
sys/arch/sh3/sh3/syscall.c Normal file
View File

@ -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 <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/sa.h>
#include <sys/savar.h>
#ifdef KTRACE
#include <sys/ktrace.h>
#endif
#ifdef SYSTRACE
#include <sys/systrace.h>
#endif
#include <sys/syscall.h>
#include <sh3/userret.h>
#include <uvm/uvm_extern.h>
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 */