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