Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/x86/lib/csum-wrappers_64.c
26424 views
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
*
18
* Returns an 32bit unfolded checksum of the buffer.
19
* src and dst are best aligned to 64bits.
20
*/
21
__wsum
22
csum_and_copy_from_user(const void __user *src, void *dst, int len)
23
{
24
__wsum sum;
25
26
might_sleep();
27
if (!user_access_begin(src, len))
28
return 0;
29
sum = csum_partial_copy_generic((__force const void *)src, dst, len);
30
user_access_end();
31
return sum;
32
}
33
34
/**
35
* csum_and_copy_to_user - Copy and checksum to user space.
36
* @src: source address
37
* @dst: destination address (user space)
38
* @len: number of bytes to be copied.
39
*
40
* Returns an 32bit unfolded checksum of the buffer.
41
* src and dst are best aligned to 64bits.
42
*/
43
__wsum
44
csum_and_copy_to_user(const void *src, void __user *dst, int len)
45
{
46
__wsum sum;
47
48
might_sleep();
49
if (!user_access_begin(dst, len))
50
return 0;
51
sum = csum_partial_copy_generic(src, (void __force *)dst, len);
52
user_access_end();
53
return sum;
54
}
55
56
/**
57
* csum_partial_copy_nocheck - Copy and checksum.
58
* @src: source address
59
* @dst: destination address
60
* @len: number of bytes to be copied.
61
*
62
* Returns an 32bit unfolded checksum of the buffer.
63
*/
64
__wsum
65
csum_partial_copy_nocheck(const void *src, void *dst, int len)
66
{
67
return csum_partial_copy_generic(src, dst, len);
68
}
69
EXPORT_SYMBOL(csum_partial_copy_nocheck);
70
71
__sum16 csum_ipv6_magic(const struct in6_addr *saddr,
72
const struct in6_addr *daddr,
73
__u32 len, __u8 proto, __wsum sum)
74
{
75
__u64 rest, sum64;
76
77
rest = (__force __u64)htonl(len) + (__force __u64)htons(proto) +
78
(__force __u64)sum;
79
80
asm(" addq (%[saddr]),%[sum]\n"
81
" adcq 8(%[saddr]),%[sum]\n"
82
" adcq (%[daddr]),%[sum]\n"
83
" adcq 8(%[daddr]),%[sum]\n"
84
" adcq $0,%[sum]\n"
85
86
: [sum] "=r" (sum64)
87
: "[sum]" (rest), [saddr] "r" (saddr), [daddr] "r" (daddr));
88
89
return csum_fold(
90
(__force __wsum)add32_with_carry(sum64 & 0xffffffff, sum64>>32));
91
}
92
EXPORT_SYMBOL(csum_ipv6_magic);
93
94