Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
arch
x86
lib
csum-wrappers_64.c
Go to the documentation of this file.
1
/*
2
* Copyright 2002, 2003 Andi Kleen, SuSE Labs.
3
* Subject to the GNU Public License v.2
4
*
5
* Wrappers of assembly checksum functions for x86-64.
6
*/
7
#include <asm/checksum.h>
8
#include <linux/module.h>
9
21
__wsum
22
csum_partial_copy_from_user
(
const
void
__user *
src
,
void
*
dst
,
23
int
len,
__wsum
isum,
int
*errp)
24
{
25
might_sleep
();
26
*errp = 0;
27
28
if
(!
likely
(
access_ok
(
VERIFY_READ
, src, len)))
29
goto
out_err;
30
31
/*
32
* Why 6, not 7? To handle odd addresses aligned we
33
* would need to do considerable complications to fix the
34
* checksum which is defined as an 16bit accumulator. The
35
* fix alignment code is primarily for performance
36
* compatibility with 32bit and that will handle odd
37
* addresses slowly too.
38
*/
39
if
(
unlikely
((
unsigned
long
)src & 6)) {
40
while
(((
unsigned
long
)src & 6) && len >= 2) {
41
__u16
val16;
42
43
*errp =
__get_user
(val16, (
const
__u16
__user
*)src);
44
if
(*errp)
45
return
isum;
46
47
*(
__u16
*)dst = val16;
48
isum = (
__force
__wsum
)add32_with_carry(
49
(
__force
unsigned
)isum, val16);
50
src += 2;
51
dst += 2;
52
len -= 2;
53
}
54
}
55
isum =
csum_partial_copy_generic
((
__force
const
void
*)src,
56
dst, len, isum, errp,
NULL
);
57
if
(
unlikely
(*errp))
58
goto
out_err;
59
60
return
isum;
61
62
out_err:
63
*errp = -
EFAULT
;
64
memset
(dst, 0, len);
65
66
return
isum;
67
}
68
EXPORT_SYMBOL
(
csum_partial_copy_from_user
);
69
81
__wsum
82
csum_partial_copy_to_user
(
const
void
*
src
,
void
__user *
dst
,
83
int
len,
__wsum
isum,
int
*errp)
84
{
85
might_sleep
();
86
87
if
(
unlikely
(!
access_ok
(
VERIFY_WRITE
, dst, len))) {
88
*errp = -
EFAULT
;
89
return
0;
90
}
91
92
if
(
unlikely
((
unsigned
long
)dst & 6)) {
93
while
(((
unsigned
long
)dst & 6) && len >= 2) {
94
__u16
val16 = *(
__u16
*)src;
95
96
isum = (
__force
__wsum
)add32_with_carry(
97
(
__force
unsigned
)isum, val16);
98
*errp =
__put_user
(val16, (
__u16
__user
*)dst);
99
if
(*errp)
100
return
isum;
101
src += 2;
102
dst += 2;
103
len -= 2;
104
}
105
}
106
107
*errp = 0;
108
return
csum_partial_copy_generic
(src, (
void
__force
*)dst,
109
len, isum,
NULL
, errp);
110
}
111
EXPORT_SYMBOL
(csum_partial_copy_to_user);
112
122
__wsum
123
csum_partial_copy_nocheck
(
const
void
*
src
,
void
*
dst
,
int
len,
__wsum
sum
)
124
{
125
return
csum_partial_copy_generic
(src, dst, len, sum,
NULL
,
NULL
);
126
}
127
EXPORT_SYMBOL
(
csum_partial_copy_nocheck
);
128
129
__sum16
csum_ipv6_magic
(
const
struct
in6_addr
*
saddr
,
130
const
struct
in6_addr
*
daddr
,
131
__u32
len,
unsigned
short
proto
,
__wsum
sum
)
132
{
133
__u64
rest
, sum64;
134
135
rest = (
__force
__u64
)
htonl
(len) + (
__force
__u64
)
htons
(proto) +
136
(
__force
__u64
)sum;
137
138
asm
(
" addq (%[saddr]),%[sum]\n"
139
" adcq 8(%[saddr]),%[sum]\n"
140
" adcq (%[daddr]),%[sum]\n"
141
" adcq 8(%[daddr]),%[sum]\n"
142
" adcq $0,%[sum]\n"
143
144
: [
sum
]
"=r"
(sum64)
145
:
"[sum]"
(rest), [
saddr
]
"r"
(
saddr
), [daddr]
"r"
(daddr));
146
147
return
csum_fold(
148
(
__force
__wsum
)add32_with_carry(sum64 & 0xffffffff, sum64>>32));
149
}
150
EXPORT_SYMBOL
(
csum_ipv6_magic
);
Generated on Thu Jan 10 2013 13:21:22 for Linux Kernel by
1.8.2