From: Ingo Molnar <[EMAIL PROTECTED]> provide an optimized assembly version of the copy_uatom() method. This is about 3 times faster than the C version.
Signed-off-by: Ingo Molnar <[EMAIL PROTECTED]> Signed-off-by: Arjan van de Ven <[EMAIL PROTECTED]> --- arch/i386/lib/getuser.S | 115 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) Index: linux/arch/i386/lib/getuser.S =================================================================== --- linux.orig/arch/i386/lib/getuser.S +++ linux/arch/i386/lib/getuser.S @@ -10,6 +10,121 @@ */ #include <asm/thread_info.h> +/* + * copy_uatom() - copy a syslet_atom from user-space into kernel-space: + */ + +.text +.align 4 +.globl copy_uatom +copy_uatom: + # + # regparm(2) call, %eax: atom, %edx: uatom + # + movl %eax, %ecx # %ecx is atom, %edx remains uatom + + cmpl $__PAGE_OFFSET-40, %edx # access_ok(uatom-sizeof(*uatom)) + jae bad_copy_uatom + + +1: movl (%edx), %eax # atom->flags = uatom->flags + movl %eax, (%ecx) + +2: movl 4(%edx), %eax # atom->nr = uatom->nr + movl %eax, 4(%ecx) + +3: movl 8(%edx), %eax # atom->ret_ptr = uatom->ret_ptr + movl %eax, 8(%ecx) + +4: movl 12(%edx), %eax # atom->next = uatom->next + movl %eax, 12(%ecx) + + +10: movl 16(%edx), %eax # atom->arg_ptr[0] = uatom->arg_ptr[0] + testl %eax, %eax + jz 20f # NULL ptr - zero out remaining args + cmpl $__PAGE_OFFSET, %eax # access_ok(arg_ptr) + jae bad_copy_uatom +100: movl (%eax), %eax + movl %eax, 16(%ecx) + +11: movl 20(%edx), %eax # atom->arg_ptr[1] = uatom->arg_ptr[1] + testl %eax, %eax + jz 21f # NULL ptr - zero out remaining args + cmpl $__PAGE_OFFSET, %eax # access_ok(arg_ptr) + jae bad_copy_uatom +110: movl (%eax), %eax + movl %eax, 20(%ecx) + +12: movl 24(%edx), %eax # atom->arg_ptr[2] = uatom->arg_ptr[2] + testl %eax, %eax + jz 22f # NULL ptr - zero out remaining args + cmpl $__PAGE_OFFSET, %eax # access_ok(arg_ptr) + jae bad_copy_uatom +120: movl (%eax), %eax + movl %eax, 24(%ecx) + +13: movl 28(%edx), %eax # atom->arg_ptr[3] = uatom->arg_ptr[3] + testl %eax, %eax + jz 23f # NULL ptr - zero out remaining args + cmpl $__PAGE_OFFSET, %eax # access_ok(arg_ptr) + jae bad_copy_uatom +130: movl (%eax), %eax + movl %eax, 28(%ecx) + +14: movl 32(%edx), %eax # atom->arg_ptr[4] = uatom->arg_ptr[4] + testl %eax, %eax + jz 24f # NULL ptr - zero out remaining args + cmpl $__PAGE_OFFSET, %eax # access_ok(arg_ptr) + jae bad_copy_uatom +140: movl (%eax), %eax + movl %eax, 32(%ecx) + +15: movl 36(%edx), %eax # atom->arg_ptr[5] = uatom->arg_ptr[5] + testl %eax, %eax + jz 25f # NULL ptr - zero out remaining args + cmpl $__PAGE_OFFSET, %eax # access_ok(arg_ptr) + jae bad_copy_uatom +150: movl (%eax), %eax + movl %eax, 36(%ecx) + + xorl %eax, %eax # return 0 + ret + + # + # Zero out arg values. Since ptr was NULL, %eax is zero: + # +20: movl %eax, 16(%ecx) # atom->args[0] = 0 +21: movl %eax, 20(%ecx) # atom->args[1] = 0 +22: movl %eax, 24(%ecx) # atom->args[2] = 0 +23: movl %eax, 28(%ecx) # atom->args[3] = 0 +24: movl %eax, 32(%ecx) # atom->args[4] = 0 +25: movl %eax, 36(%ecx) # atom->args[5] = 0 + + ret # return 0 + +bad_copy_uatom: + movl $-14, %eax + ret + +.section __ex_table,"a" + .long 1b, bad_copy_uatom + .long 2b, bad_copy_uatom + .long 3b, bad_copy_uatom + .long 4b, bad_copy_uatom + .long 10b, bad_copy_uatom + .long 100b, bad_copy_uatom + .long 11b, bad_copy_uatom + .long 110b, bad_copy_uatom + .long 12b, bad_copy_uatom + .long 120b, bad_copy_uatom + .long 13b, bad_copy_uatom + .long 130b, bad_copy_uatom + .long 14b, bad_copy_uatom + .long 140b, bad_copy_uatom + .long 15b, bad_copy_uatom + .long 150b, bad_copy_uatom +.previous /* * __get_user_X - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/