Skip to content

Commit

Permalink
x86: clean up csum-wrappers_64.c some more
Browse files Browse the repository at this point in the history
no code changed:

arch/x86/lib/csum-wrappers_64.o:
   text    data     bss     dec     hex filename
    839       0       0     839     347 csum-wrappers_64.o.before
    839       0       0     839     347 csum-wrappers_64.o.after
md5:
b31994226c33e0b52bef5a0e110b84b0  csum-wrappers_64.o.before.asm
b31994226c33e0b52bef5a0e110b84b0  csum-wrappers_64.o.after.asm

Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
  • Loading branch information
Ingo Molnar committed Feb 19, 2008
1 parent 0df025b commit d76c1ae
Showing 1 changed file with 51 additions and 36 deletions.
87 changes: 51 additions & 36 deletions arch/x86/lib/csum-wrappers_64.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/* Copyright 2002,2003 Andi Kleen, SuSE Labs.
/*
* Copyright 2002, 2003 Andi Kleen, SuSE Labs.
* Subject to the GNU Public License v.2
*
* Wrappers of assembly checksum functions for x86-64.
*/

#include <asm/checksum.h>
#include <linux/module.h>

Expand All @@ -24,37 +24,47 @@ csum_partial_copy_from_user(const void __user *src, void *dst,
{
might_sleep();
*errp = 0;
if (likely(access_ok(VERIFY_READ, src, len))) {
/* Why 6, not 7? To handle odd addresses aligned we
would need to do considerable complications to fix the
checksum which is defined as an 16bit accumulator. The
fix alignment code is primarily for performance
compatibility with 32bit and that will handle odd
addresses slowly too. */
if (unlikely((unsigned long)src & 6)) {
while (((unsigned long)src & 6) && len >= 2) {
__u16 val16;
*errp = __get_user(val16, (const __u16 __user *)src);
if (*errp)
return isum;
*(__u16 *)dst = val16;
isum = (__force __wsum)add32_with_carry(
(__force unsigned)isum, val16);
src += 2;
dst += 2;
len -= 2;
}

if (!likely(access_ok(VERIFY_READ, src, len)))
goto out_err;

/*
* Why 6, not 7? To handle odd addresses aligned we
* would need to do considerable complications to fix the
* checksum which is defined as an 16bit accumulator. The
* fix alignment code is primarily for performance
* compatibility with 32bit and that will handle odd
* addresses slowly too.
*/
if (unlikely((unsigned long)src & 6)) {
while (((unsigned long)src & 6) && len >= 2) {
__u16 val16;

*errp = __get_user(val16, (const __u16 __user *)src);
if (*errp)
return isum;

*(__u16 *)dst = val16;
isum = (__force __wsum)add32_with_carry(
(__force unsigned)isum, val16);
src += 2;
dst += 2;
len -= 2;
}
isum = csum_partial_copy_generic((__force const void *)src,
dst, len, isum, errp, NULL);
if (likely(*errp == 0))
return isum;
}
isum = csum_partial_copy_generic((__force const void *)src,
dst, len, isum, errp, NULL);
if (unlikely(*errp))
goto out_err;

return isum;

out_err:
*errp = -EFAULT;
memset(dst, 0, len);

return isum;
}

EXPORT_SYMBOL(csum_partial_copy_from_user);

/**
Expand All @@ -73,6 +83,7 @@ csum_partial_copy_to_user(const void *src, void __user *dst,
int len, __wsum isum, int *errp)
{
might_sleep();

if (unlikely(!access_ok(VERIFY_WRITE, dst, len))) {
*errp = -EFAULT;
return 0;
Expand All @@ -81,6 +92,7 @@ csum_partial_copy_to_user(const void *src, void __user *dst,
if (unlikely((unsigned long)dst & 6)) {
while (((unsigned long)dst & 6) && len >= 2) {
__u16 val16 = *(__u16 *)src;

isum = (__force __wsum)add32_with_carry(
(__force unsigned)isum, val16);
*errp = __put_user(val16, (__u16 __user *)dst);
Expand All @@ -93,9 +105,9 @@ csum_partial_copy_to_user(const void *src, void __user *dst,
}

*errp = 0;
return csum_partial_copy_generic(src, (void __force *)dst, len, isum, NULL, errp);
return csum_partial_copy_generic(src, (void __force *)dst,
len, isum, NULL, errp);
}

EXPORT_SYMBOL(csum_partial_copy_to_user);

/**
Expand All @@ -122,14 +134,17 @@ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,

rest = (__force __u64)htonl(len) + (__force __u64)htons(proto) +
(__force __u64)sum;
asm(" addq (%[saddr]),%[sum]\n"
" adcq 8(%[saddr]),%[sum]\n"
" adcq (%[daddr]),%[sum]\n"
" adcq 8(%[daddr]),%[sum]\n"
" adcq $0,%[sum]\n"

asm(" addq (%[saddr]),%[sum]\n"
" adcq 8(%[saddr]),%[sum]\n"
" adcq (%[daddr]),%[sum]\n"
" adcq 8(%[daddr]),%[sum]\n"
" adcq $0,%[sum]\n"

: [sum] "=r" (sum64)
: "[sum]" (rest), [saddr] "r" (saddr), [daddr] "r" (daddr));
return csum_fold((__force __wsum)add32_with_carry(sum64 & 0xffffffff, sum64>>32));
}

return csum_fold(
(__force __wsum)add32_with_carry(sum64 & 0xffffffff, sum64>>32));
}
EXPORT_SYMBOL(csum_ipv6_magic);

0 comments on commit d76c1ae

Please sign in to comment.