diff options
author | Justus Winter <4winter@informatik.uni-hamburg.de> | 2014-12-19 01:51:58 +0100 |
---|---|---|
committer | Justus Winter <4winter@informatik.uni-hamburg.de> | 2015-02-20 19:14:22 +0100 |
commit | d3f20b06cee70fd5afe8aaff31614756a57e6bb6 (patch) | |
tree | c48f6c2aefd471dfad91c22396be360bffb604b7 /i386 | |
parent | 5bf4c1cb311ade33ea2c4b3706f7c6a42917b008 (diff) |
i386: specialize `copyinmsg' and `copyoutmsg'
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.
(copyoutmsg): New function.
Diffstat (limited to 'i386')
-rw-r--r-- | i386/i386/locore.S | 83 |
1 files changed, 79 insertions, 4 deletions
diff --git a/i386/i386/locore.S b/i386/i386/locore.S index 2e04bb8..cfda86f 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,48 @@ 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(copyinmsg_fail) + rep + movsl /* move longwords */ + xorl %eax,%eax /* return 0 for success */ + +copyinmsg_ret: + mov %ss,%di /* restore DS to kernel segment */ + mov %di,%ds + + popl %edi /* restore registers */ + popl %esi + ret /* and return */ + +copyinmsg_fail: + movl $1,%eax /* return 1 for failure */ + jmp copyinmsg_ret /* pop frame 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 */ @@ -1322,6 +1356,47 @@ 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(copyoutmsg_fail) + rep + movsl + xorl %eax,%eax /* return 0 for success */ + +copyoutmsg_ret: + mov %ss,%di /* restore ES to kernel segment */ + mov %di,%es + + popl %edi /* restore registers */ + popl %esi + ret /* and return */ + +copyoutmsg_fail: + movl $1,%eax /* return 1 for failure */ + jmp copyoutmsg_ret /* pop frame and return */ + #if !defined(MACH_HYP) && !PAE /* * Check whether user address space is writable |