bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH gnumach 2/3] i386: specialize `copyinmsg' and `copyoutmsg'


From: Justus Winter
Subject: [PATCH gnumach 2/3] i386: specialize `copyinmsg' and `copyoutmsg'
Date: Fri, 19 Dec 2014 02:48:57 +0100

Previously, `copyinmsg' was the same function as `copyin'.  The former
is for messages, and the size of messages is a multiple of four.
Likewise for `copyoutmsg'.

Provide a specialized version of both functions.  This shaves off a
couple of instructions and improves our IPC performance.

* i386/i386/locore.S (copyinmsg): New function.
(copyout): Do not needlessly copy length to %eax first.
(copyoutmsg): New function.
---
 i386/i386/locore.S | 78 +++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 71 insertions(+), 7 deletions(-)

diff --git a/i386/i386/locore.S b/i386/i386/locore.S
index 15715f6..ab17879 100644
--- a/i386/i386/locore.S
+++ b/i386/i386/locore.S
@@ -1232,13 +1232,12 @@ ENTRY(discover_x86_cpu_type)
  */
 
 /*
- * Copy from user address space.
+ * Copy from user address space - generic version.
  * arg0:       user address
  * arg1:       kernel address
  * arg2:       byte count
  */
 ENTRY(copyin)
-Entry(copyinmsg)
        pushl   %esi
        pushl   %edi                    /* save registers */
 
@@ -1275,13 +1274,43 @@ copyin_fail:
        jmp     copyin_ret              /* pop frame and return */
 
 /*
- * Copy to user address space.
+ * Copy from user address space - version for copying messages.
+ * arg0:       user address
+ * arg1:       kernel address
+ * arg2:       byte count - must be a multiple of four
+ */
+ENTRY(copyinmsg)
+       pushl   %esi
+       pushl   %edi                    /* save registers */
+
+       movl    8+S_ARG0,%esi           /* get user start address */
+       movl    8+S_ARG1,%edi           /* get kernel destination address */
+       movl    8+S_ARG2,%ecx           /* get count */
+
+       movl    $USER_DS,%eax           /* use user data segment for accesses */
+       mov     %ax,%ds
+
+       /*cld*/                         /* count up: default mode in all GCC 
code */
+       shrl    $2,%ecx
+       RECOVER(copyin_fail)
+       rep
+       movsl                           /* move longwords */
+       xorl    %eax,%eax               /* return 0 for success */
+
+       mov     %ss,%di                 /* restore DS to kernel segment */
+       mov     %di,%ds
+
+       popl    %edi                    /* restore registers */
+       popl    %esi
+       ret                             /* and return */
+
+/*
+ * Copy to user address space - generic version.
  * arg0:       kernel address
  * arg1:       user address
  * arg2:       byte count
  */
 ENTRY(copyout)
-Entry(copyoutmsg)
        pushl   %esi
        pushl   %edi                    /* save registers */
 
@@ -1297,14 +1326,13 @@ Entry(copyoutmsg)
        jbe     copyout_retry           /* Use slow version on i386 */
 #endif /* !defined(MACH_HYP) && !PAE */
 
-       movl    %edx,%eax               /* use count */
        /*cld*/                         /* count up: always this way in GCC 
code */
-       movl    %eax,%ecx               /* move by longwords first */
+       movl    %edx,%ecx               /* move by longwords first */
        shrl    $2,%ecx
        RECOVER(copyout_fail)
        rep
        movsl
-       movl    %eax,%ecx               /* now move remaining bytes */
+       movl    %edx,%ecx               /* now move remaining bytes */
        andl    $3,%ecx
        RECOVER(copyout_fail)
        rep
@@ -1323,6 +1351,42 @@ copyout_fail:
        movl    $1,%eax                 /* return 1 for failure */
        jmp     copyout_ret             /* pop frame and return */
 
+/*
+ * Copy to user address space - version for copying messages.
+ * arg0:       kernel address
+ * arg1:       user address
+ * arg2:       byte count - must be a multiple of four
+ */
+ENTRY(copyoutmsg)
+       pushl   %esi
+       pushl   %edi                    /* save registers */
+
+       movl    8+S_ARG0,%esi           /* get kernel start address */
+       movl    8+S_ARG1,%edi           /* get user start address */
+       movl    8+S_ARG2,%ecx           /* get count */
+
+       movl    $USER_DS,%eax           /* use user data segment for accesses */
+       mov     %ax,%es
+
+#if !defined(MACH_HYP) && !PAE
+       movl    8+S_ARG2,%edx           /* copyout_retry expects count here */
+       cmpl    $3,machine_slot+SUB_TYPE_CPU_TYPE
+       jbe     copyout_retry           /* Use slow version on i386 */
+#endif /* !defined(MACH_HYP) && !PAE */
+
+       shrl    $2,%ecx                 /* move by longwords */
+       RECOVER(copyout_fail)
+       rep
+       movsl
+       xorl    %eax,%eax               /* return 0 for success */
+
+       mov     %ss,%di                 /* restore ES to kernel segment */
+       mov     %di,%es
+
+       popl    %edi                    /* restore registers */
+       popl    %esi
+       ret                             /* and return */
+
 #if !defined(MACH_HYP) && !PAE
 /*
  * Check whether user address space is writable
-- 
2.1.3




reply via email to

[Prev in Thread] Current Thread [Next in Thread]