linux/arch/x86/lib/csum-wrappers_64.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright 2002, 2003 Andi Kleen, SuSE Labs.
   4 *
   5 * Wrappers of assembly checksum functions for x86-64.
   6 */
   7#include <asm/checksum.h>
   8#include <linux/export.h>
   9#include <linux/uaccess.h>
  10#include <asm/smap.h>
  11
  12/**
  13 * csum_and_copy_from_user - Copy and checksum from user space.
  14 * @src: source address (user space)
  15 * @dst: destination address
  16 * @len: number of bytes to be copied.
  17 * @isum: initial sum that is added into the result (32bit unfolded)
  18 * @errp: set to -EFAULT for an bad source address.
  19 *
  20 * Returns an 32bit unfolded checksum of the buffer.
  21 * src and dst are best aligned to 64bits.
  22 */
  23__wsum
  24csum_and_copy_from_user(const void __user *src, void *dst, int len)
  25{
  26        __wsum sum;
  27
  28        might_sleep();
  29        if (!user_access_begin(src, len))
  30                return 0;
  31        sum = csum_partial_copy_generic((__force const void *)src, dst, len);
  32        user_access_end();
  33        return sum;
  34}
  35EXPORT_SYMBOL(csum_and_copy_from_user);
  36
  37/**
  38 * csum_and_copy_to_user - Copy and checksum to user space.
  39 * @src: source address
  40 * @dst: destination address (user space)
  41 * @len: number of bytes to be copied.
  42 * @isum: initial sum that is added into the result (32bit unfolded)
  43 * @errp: set to -EFAULT for an bad destination address.
  44 *
  45 * Returns an 32bit unfolded checksum of the buffer.
  46 * src and dst are best aligned to 64bits.
  47 */
  48__wsum
  49csum_and_copy_to_user(const void *src, void __user *dst, int len)
  50{
  51        __wsum sum;
  52
  53        might_sleep();
  54        if (!user_access_begin(dst, len))
  55                return 0;
  56        sum = csum_partial_copy_generic(src, (void __force *)dst, len);
  57        user_access_end();
  58        return sum;
  59}
  60EXPORT_SYMBOL(csum_and_copy_to_user);
  61
  62/**
  63 * csum_partial_copy_nocheck - Copy and checksum.
  64 * @src: source address
  65 * @dst: destination address
  66 * @len: number of bytes to be copied.
  67 * @sum: initial sum that is added into the result (32bit unfolded)
  68 *
  69 * Returns an 32bit unfolded checksum of the buffer.
  70 */
  71__wsum
  72csum_partial_copy_nocheck(const void *src, void *dst, int len)
  73{
  74        return csum_partial_copy_generic(src, dst, len);
  75}
  76EXPORT_SYMBOL(csum_partial_copy_nocheck);
  77
  78__sum16 csum_ipv6_magic(const struct in6_addr *saddr,
  79                        const struct in6_addr *daddr,
  80                        __u32 len, __u8 proto, __wsum sum)
  81{
  82        __u64 rest, sum64;
  83
  84        rest = (__force __u64)htonl(len) + (__force __u64)htons(proto) +
  85                (__force __u64)sum;
  86
  87        asm("   addq (%[saddr]),%[sum]\n"
  88            "   adcq 8(%[saddr]),%[sum]\n"
  89            "   adcq (%[daddr]),%[sum]\n"
  90            "   adcq 8(%[daddr]),%[sum]\n"
  91            "   adcq $0,%[sum]\n"
  92
  93            : [sum] "=r" (sum64)
  94            : "[sum]" (rest), [saddr] "r" (saddr), [daddr] "r" (daddr));
  95
  96        return csum_fold(
  97               (__force __wsum)add32_with_carry(sum64 & 0xffffffff, sum64>>32));
  98}
  99EXPORT_SYMBOL(csum_ipv6_magic);
 100