kernel - Optimize syscall path, remove old unused compat code
authorMatthew Dillon <dillon@apollo.backplane.com>
Fri, 4 May 2018 17:48:29 +0000 (10:48 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Tue, 8 May 2018 17:01:20 +0000 (10:01 -0700)
* Use the built-in memcpy with a constant length for the register arg
  copy instead of calling bcopy().  This saves us 25ns.

* Remove several system call compatibility support features that are
  no longer used (as we no longer have a linux compat module).  We
  remove sv_mask and sv_prepsyscall.  Saves 1ns (woo woo!).

* Do some minor rearrangement of code to remove additional unnecessary
  conditionals.

sys/cpu/x86_64/misc/elf_machdep.c
sys/kern/imgact_aout.c
sys/platform/pc64/x86_64/trap.c
sys/platform/vkernel64/x86_64/trap.c
sys/sys/sysent.h

index ed93490..eb659b1 100644 (file)
@@ -40,7 +40,6 @@
 static struct sysentvec elf64_dragonfly_sysvec = {
         .sv_size       = SYS_MAXSYSCALL,
         .sv_table      = sysent,
-        .sv_mask       = -1,
         .sv_sigsize    = 0,
         .sv_sigtbl     = NULL,
         .sv_errsize    = 0,
@@ -50,7 +49,6 @@ static struct sysentvec elf64_dragonfly_sysvec = {
         .sv_sendsig    = sendsig,
         .sv_sigcode    = sigcode,
         .sv_szsigcode  = &szsigcode,
-        .sv_prepsyscall        = NULL,
        .sv_name        = "DragonFly ELF64",
        .sv_coredump    = __elfN(coredump),
        .sv_imgact_try  = NULL,
index faca67a..509cee5 100644 (file)
@@ -59,7 +59,6 @@ static int    exec_aout_imgact (struct image_params *imgp);
 struct sysentvec aout_sysvec = {
        SYS_MAXSYSCALL,
        sysent,
-       -1,
        0,
        0,
        0,
@@ -69,7 +68,6 @@ struct sysentvec aout_sysvec = {
        sendsig,
        sigcode,
        &szsigcode,
-       0,
        "FreeBSD a.out",
        NULL,
        NULL,
index 3016250..742d03e 100644 (file)
@@ -1111,7 +1111,6 @@ syscall2(struct trapframe *frame)
        struct thread *td = curthread;
        struct proc *p = td->td_proc;
        struct lwp *lp = td->td_lwp;
-       caddr_t params;
        struct sysent *callp;
        register_t orig_tf_rflags;
        int sticks;
@@ -1122,7 +1121,7 @@ syscall2(struct trapframe *frame)
 #endif
        register_t *argp;
        u_int code;
-       int regregcnt;
+       int regcnt, optimized_regcnt;
        union sysunion args;
        register_t *argsdst;
 
@@ -1140,8 +1139,9 @@ syscall2(struct trapframe *frame)
 
        userenter(td, p);       /* lazy raise our priority */
 
-       reg = 0;
        regcnt = 6;
+       optimized_regcnt = 6;
+
        /*
         * Misc
         */
@@ -1158,6 +1158,7 @@ syscall2(struct trapframe *frame)
                vkernel_trap(lp, frame);
                error = EJUSTRETURN;
                callp = NULL;
+               code = 0;
                goto out;
        }
 
@@ -1166,24 +1167,16 @@ syscall2(struct trapframe *frame)
         */
        KASSERT(lp->lwp_md.md_regs == frame,
                ("Frame mismatch %p %p", lp->lwp_md.md_regs, frame));
-       params = (caddr_t)frame->tf_rsp + sizeof(register_t);
-       code = frame->tf_rax;
+       code = (u_int)frame->tf_rax;
 
-       if (p->p_sysent->sv_prepsyscall) {
-               (*p->p_sysent->sv_prepsyscall)(
-                       frame, (int *)(&args.nosys.sysmsg + 1),
-                       &code, &params);
+       if (code == SYS_syscall || code == SYS___syscall) {
+               code = frame->tf_rdi;
+               regcnt--;
+               argp = &frame->tf_rdi + 1;
        } else {
-               if (code == SYS_syscall || code == SYS___syscall) {
-                       code = frame->tf_rdi;
-                       reg++;
-                       regcnt--;
-               }
+               argp = &frame->tf_rdi;
        }
 
-       if (p->p_sysent->sv_mask)
-               code &= p->p_sysent->sv_mask;
-
        if (code >= p->p_sysent->sv_size)
                callp = &p->p_sysent->sv_table[0];
        else
@@ -1197,21 +1190,24 @@ syscall2(struct trapframe *frame)
         * to be the registers used to pass arguments, in exactly the right
         * order.
         */
-       argp = &frame->tf_rdi;
-       argp += reg;
        argsdst = (register_t *)(&args.nosys.sysmsg + 1);
+
        /*
-        * JG can we overflow the space pointed to by 'argsdst'
-        * either with 'bcopy' or with 'copyin'?
+        * Its easier to copy up to the highest number of syscall arguments
+        * passed in registers, which is 6, than to conditionalize it.
         */
-       bcopy(argp, argsdst, sizeof(register_t) * regcnt);
+       __builtin_memcpy(argsdst, argp, sizeof(register_t) * optimized_regcnt);
+
        /*
-        * copyin is MP aware, but the tracing code is not
+        * Any arguments beyond available argument-passing registers must
+        * be copyin()'d from the user stack.
         */
        if (narg > regcnt) {
-               KASSERT(params != NULL, ("copyin args with no params!"));
+               caddr_t params;
+
+               params = (caddr_t)frame->tf_rsp + sizeof(register_t);
                error = copyin(params, &argsdst[regcnt],
-                       (narg - regcnt) * sizeof(register_t));
+                              (narg - regcnt) * sizeof(register_t));
                if (error) {
 #ifdef KTRACE
                        if (KTRPOINT(td, KTR_SYSCALL)) {
index 012757d..cd79184 100644 (file)
@@ -1095,21 +1095,12 @@ syscall2(struct trapframe *frame)
        params = (caddr_t)frame->tf_rsp + sizeof(register_t);
        code = frame->tf_rax;
 
-       if (p->p_sysent->sv_prepsyscall) {
-               (*p->p_sysent->sv_prepsyscall)(
-                       frame, (int *)(&args.nosys.sysmsg + 1),
-                       &code, &params);
-       } else {
-               if (code == SYS_syscall || code == SYS___syscall) {
-                       code = frame->tf_rdi;
-                       reg++;
-                       regcnt--;
-               }
+       if (code == SYS_syscall || code == SYS___syscall) {
+               code = frame->tf_rdi;
+               reg++;
+               regcnt--;
        }
 
-       if (p->p_sysent->sv_mask)
-               code &= p->p_sysent->sv_mask;
-
        if (code >= p->p_sysent->sv_size)
                callp = &p->p_sysent->sv_table[0];
        else
index 4907b55..811f11f 100644 (file)
@@ -60,7 +60,6 @@ struct vnode;
 struct sysentvec {
        int             sv_size;        /* number of entries */
        struct sysent   *sv_table;      /* pointer to sysent */
-       u_int           sv_mask;        /* optional mask to index, else -1 */
        int             sv_sigsize;     /* size of signal translation table */
        int             *sv_sigtbl;     /* signal translation table */
        int             sv_errsize;     /* size of errno translation table */
@@ -75,8 +74,6 @@ struct sysentvec {
        char            *sv_sigcode;    /* start of sigtramp code */
        int             *sv_szsigcode;  /* size of sigtramp code */
                                        /* prep syscall (must be MPSAFE) */
-       void            (*sv_prepsyscall) (struct trapframe *, int *,
-                                              u_int *, caddr_t *);
        char            *sv_name;       /* name of binary type */
        int             (*sv_coredump) (struct lwp *, int, struct vnode *,
                                            off_t);