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