Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys Do the syscall_plain/syscall_fancy dance on ARM. Shaves...
details: https://anonhg.NetBSD.org/src/rev/7b0e4772aad0
branches: trunk
changeset: 543613:7b0e4772aad0
user: thorpej <thorpej%NetBSD.org@localhost>
date: Sat Mar 01 04:36:38 2003 +0000
description:
Do the syscall_plain/syscall_fancy dance on ARM. Shaves a fair number
of cycles off the syscall overhead.
Since all COMPAT_LINUX platforms now support __HAVE_SYSCALL_INTERN,
garbage-collect the LINUX_SYSCALL_FUNCTION stuff.
diffstat:
sys/arch/arm/arm/linux_syscall.c | 78 +++++++++++++-
sys/arch/arm/arm/syscall.c | 150 +++++++++++++++++++++++++++-
sys/arch/arm/include/proc.h | 5 +-
sys/arch/arm/include/types.h | 3 +-
sys/compat/linux/arch/arm/linux_exec.h | 4 +-
sys/compat/linux/arch/arm/linux_machdep.h | 4 +-
sys/compat/linux/arch/powerpc/linux_exec.h | 5 +-
sys/compat/linux/common/linux_exec.c | 9 +-
8 files changed, 227 insertions(+), 31 deletions(-)
diffs (truncated from 413 to 300 lines):
diff -r 05fb6e9666da -r 7b0e4772aad0 sys/arch/arm/arm/linux_syscall.c
--- a/sys/arch/arm/arm/linux_syscall.c Sat Mar 01 04:20:54 2003 +0000
+++ b/sys/arch/arm/arm/linux_syscall.c Sat Mar 01 04:36:38 2003 +0000
@@ -1,7 +1,7 @@
-/* $NetBSD: linux_syscall.c,v 1.8 2003/01/17 22:28:48 thorpej Exp $ */
+/* $NetBSD: linux_syscall.c,v 1.9 2003/03/01 04:36:38 thorpej Exp $ */
/*-
- * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * Copyright (c) 2000, 2003 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -80,7 +80,7 @@
#include <sys/param.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_syscall.c,v 1.8 2003/01/17 22:28:48 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_syscall.c,v 1.9 2003/03/01 04:36:38 thorpej Exp $");
#include <sys/device.h>
#include <sys/errno.h>
@@ -110,11 +110,77 @@
#define LINUX_ARM_NR_BASE 0x9f0000
#define LINUX_SYS_ARMBASE 0x000100 /* Must agree with syscalls.master */
-/* XXX */
-void linux_syscall(struct trapframe *frame, struct lwp *l, u_int32_t insn);
+void linux_syscall_intern(struct proc *);
+void linux_syscall_plain(struct trapframe *, struct lwp *, u_int32_t);
+void linux_syscall_fancy(struct trapframe *, struct lwp *, u_int32_t);
+
+void
+linux_syscall_intern(struct proc *p)
+{
+#ifdef KTRACE
+ if (p->p_traceflag & (KTRFAC_SYSCALL | KTRFAC_SYSRET)) {
+ p->p_md.md_syscall = linux_syscall_fancy;
+ return;
+ }
+#endif
+#ifdef SYSTRACE
+ if (p->p_flag & P_SYSTRACE) {
+ p->p_md.md_syscall = linux_syscall_fancy;
+ return;
+ }
+#endif
+ p->p_md.md_syscall = linux_syscall_plain;
+}
void
-linux_syscall(trapframe_t *frame, struct lwp *l, u_int32_t insn)
+linux_syscall_plain(trapframe_t *frame, struct lwp *l, u_int32_t insn)
+{
+ const struct sysent *callp;
+ struct proc *p = l->l_proc;
+ int code, error;
+ u_int nargs;
+ register_t *args, rval[2];
+
+ code = insn & 0x00ffffff;
+ /* Remap ARM-specific syscalls onto the end of the standard range. */
+ if (code > LINUX_ARM_NR_BASE)
+ code = code - LINUX_ARM_NR_BASE + LINUX_SYS_ARMBASE;
+ code &= LINUX_SYS_NSYSENT - 1;
+
+ /* Linux passes all arguments in order in registers, which is nice. */
+ args = &frame->tf_r0;
+ callp = p->p_emul->e_sysent + code;
+ nargs = callp->sy_argsize / sizeof(register_t);
+
+ rval[0] = 0;
+ rval[1] = 0;
+ error = (*callp->sy_call)(l, args, rval);
+
+ switch (error) {
+ case 0:
+ frame->tf_r0 = rval[0];
+ break;
+
+ case ERESTART:
+ /* Reconstruct the pc to point at the swi. */
+ frame->tf_pc -= INSN_SIZE;
+ break;
+
+ case EJUSTRETURN:
+ /* nothing to do */
+ break;
+
+ default:
+ error = native_to_linux_errno[error];
+ frame->tf_r0 = error;
+ break;
+ }
+
+ userret(l);
+}
+
+void
+linux_syscall_fancy(trapframe_t *frame, struct lwp *l, u_int32_t insn)
{
const struct sysent *callp;
struct proc *p = l->l_proc;
diff -r 05fb6e9666da -r 7b0e4772aad0 sys/arch/arm/arm/syscall.c
--- a/sys/arch/arm/arm/syscall.c Sat Mar 01 04:20:54 2003 +0000
+++ b/sys/arch/arm/arm/syscall.c Sat Mar 01 04:36:38 2003 +0000
@@ -1,7 +1,7 @@
-/* $NetBSD: syscall.c,v 1.15 2003/01/17 22:28:49 thorpej Exp $ */
+/* $NetBSD: syscall.c,v 1.16 2003/03/01 04:36:38 thorpej Exp $ */
/*-
- * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * Copyright (c) 2000, 2003 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -82,7 +82,7 @@
#include <sys/param.h>
-__KERNEL_RCSID(0, "$NetBSD: syscall.c,v 1.15 2003/01/17 22:28:49 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: syscall.c,v 1.16 2003/03/01 04:36:38 thorpej Exp $");
#include <sys/device.h>
#include <sys/errno.h>
@@ -171,16 +171,150 @@
uvmexp.syscalls++;
(*(void(*)(struct trapframe *, struct lwp *, u_int32_t))
- (p->p_emul->e_syscall))(frame, l, insn);
+ (p->p_md.md_syscall))(frame, l, insn);
}
#define MAXARGS 8
-/* XXX */
-void syscall(struct trapframe *frame, struct lwp *l, u_int32_t insn);
+void syscall_intern(struct proc *);
+void syscall_plain(struct trapframe *, struct lwp *, u_int32_t);
+void syscall_fancy(struct trapframe *, struct lwp *, u_int32_t);
+
+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 (p->p_flag & P_SYSTRACE) {
+ p->p_md.md_syscall = syscall_fancy;
+ return;
+ }
+#endif
+ p->p_md.md_syscall = syscall_plain;
+}
void
-syscall(struct trapframe *frame, struct lwp *l, u_int32_t insn)
+syscall_plain(struct trapframe *frame, struct lwp *l, u_int32_t insn)
+{
+ struct proc *p = l->l_proc;
+ const struct sysent *callp;
+ int code, error;
+ u_int nap, nargs;
+ register_t *ap, *args, copyargs[MAXARGS], rval[2];
+
+ KERNEL_PROC_LOCK(p);
+
+ switch (insn & SWI_OS_MASK) { /* Which OS is the SWI from? */
+ case SWI_OS_ARM: /* ARM-defined SWIs */
+ code = insn & 0x00ffffff;
+ switch (code) {
+ case SWI_IMB:
+ case SWI_IMBrange:
+ /*
+ * Do nothing as there is no prefetch unit that needs
+ * flushing
+ */
+ break;
+ default:
+ /* Undefined so illegal instruction */
+ trapsignal(l, SIGILL, insn);
+ break;
+ }
+
+ userret(l);
+ return;
+ case 0x000000: /* Old unofficial NetBSD range. */
+ case SWI_OS_NETBSD: /* New official NetBSD range. */
+ nap = 4;
+ break;
+ default:
+ /* Undefined so illegal instruction */
+ trapsignal(l, SIGILL, insn);
+ userret(l);
+ return;
+ }
+
+ code = insn & 0x000fffff;
+
+ ap = &frame->tf_r0;
+ callp = p->p_emul->e_sysent;
+
+ switch (code) {
+ case SYS_syscall:
+ code = *ap++;
+ nap--;
+ break;
+ case SYS___syscall:
+ code = ap[_QUAD_LOWWORD];
+ ap += 2;
+ nap -= 2;
+ break;
+ }
+
+ code &= (SYS_NSYSENT - 1);
+ callp += code;
+ nargs = callp->sy_argsize / sizeof(register_t);
+ if (nargs <= nap)
+ args = ap;
+ else {
+ KASSERT(nargs <= MAXARGS);
+ memcpy(copyargs, ap, nap * sizeof(register_t));
+ error = copyin((void *)frame->tf_usr_sp, copyargs + nap,
+ (nargs - nap) * sizeof(register_t));
+ if (error)
+ goto bad;
+ args = copyargs;
+ }
+
+ rval[0] = 0;
+ rval[1] = 0;
+ error = (*callp->sy_call)(l, args, rval);
+
+ switch (error) {
+ case 0:
+ frame->tf_r0 = rval[0];
+ frame->tf_r1 = rval[1];
+
+#ifdef __PROG32
+ frame->tf_spsr &= ~PSR_C_bit; /* carry bit */
+#else
+ frame->tf_r15 &= ~R15_FLAG_C; /* carry bit */
+#endif
+ break;
+
+ case ERESTART:
+ /*
+ * Reconstruct the pc to point at the swi.
+ */
+ frame->tf_pc -= INSN_SIZE;
+ break;
+
+ case EJUSTRETURN:
+ /* nothing to do */
+ break;
+
+ default:
+ bad:
+ frame->tf_r0 = error;
+#ifdef __PROG32
+ frame->tf_spsr |= PSR_C_bit; /* carry bit */
+#else
+ frame->tf_r15 |= R15_FLAG_C; /* carry bit */
+#endif
+ break;
+ }
+
+ KERNEL_PROC_UNLOCK(l);
+ userret(l);
+}
+
+void
+syscall_fancy(struct trapframe *frame, struct lwp *l, u_int32_t insn)
{
struct proc *p = l->l_proc;
const struct sysent *callp;
@@ -325,5 +459,3 @@
}
#endif
}
-
-/* End of syscall.c */
diff -r 05fb6e9666da -r 7b0e4772aad0 sys/arch/arm/include/proc.h
--- a/sys/arch/arm/include/proc.h Sat Mar 01 04:20:54 2003 +0000
+++ b/sys/arch/arm/include/proc.h Sat Mar 01 04:36:38 2003 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: proc.h,v 1.4 2003/01/17 22:28:48 thorpej Exp $ */
+/* $NetBSD: proc.h,v 1.5 2003/03/01 04:36:39 thorpej Exp $ */
/*
* Copyright (c) 1994 Mark Brinicombe.
@@ -39,11 +39,14 @@
* Machine-dependent part of the proc structure for arm.
*/
+struct trapframe;
Home |
Main Index |
Thread Index |
Old Index