aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@s-opensource.com>2017-05-17 08:16:19 -0400
committerJonathan Corbet <corbet@lwn.net>2017-07-14 15:58:09 -0400
commitc6ebaf6bdb10469910afdcfc6af5c26846883e98 (patch)
treeaa54085051f46e5c09bd114f63ffa853e797d949
parent79ab3b0d21ea1ac48ce0e6b44997dd0a8c8f72e6 (diff)
unaligned-memory-access.txt: standardize document format
Each text file under Documentation follows a different format. Some doesn't even have titles! Change its representation to follow the adopted standard, using ReST markups for it to be parseable by Sphinx: - promote document title one level; - use markups for authorship and put it at the beginning; - mark literal blocks; - adjust identation. Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> Signed-off-by: Jonathan Corbet <corbet@lwn.net>
-rw-r--r--Documentation/unaligned-memory-access.txt57
1 files changed, 30 insertions, 27 deletions
diff --git a/Documentation/unaligned-memory-access.txt b/Documentation/unaligned-memory-access.txt
index 3f76c0c37920..51b4ff031586 100644
--- a/Documentation/unaligned-memory-access.txt
+++ b/Documentation/unaligned-memory-access.txt
@@ -1,6 +1,15 @@
1=========================
1UNALIGNED MEMORY ACCESSES 2UNALIGNED MEMORY ACCESSES
2========================= 3=========================
3 4
5:Author: Daniel Drake <dsd@gentoo.org>,
6:Author: Johannes Berg <johannes@sipsolutions.net>
7
8:With help from: Alan Cox, Avuton Olrich, Heikki Orsila, Jan Engelhardt,
9 Kyle McMartin, Kyle Moffett, Randy Dunlap, Robert Hancock, Uli Kunitz,
10 Vadim Lobanov
11
12
4Linux runs on a wide variety of architectures which have varying behaviour 13Linux runs on a wide variety of architectures which have varying behaviour
5when it comes to memory access. This document presents some details about 14when it comes to memory access. This document presents some details about
6unaligned accesses, why you need to write code that doesn't cause them, 15unaligned accesses, why you need to write code that doesn't cause them,
@@ -73,7 +82,7 @@ memory addresses of certain variables, etc.
73 82
74Fortunately things are not too complex, as in most cases, the compiler 83Fortunately things are not too complex, as in most cases, the compiler
75ensures that things will work for you. For example, take the following 84ensures that things will work for you. For example, take the following
76structure: 85structure::
77 86
78 struct foo { 87 struct foo {
79 u16 field1; 88 u16 field1;
@@ -106,7 +115,7 @@ On a related topic, with the above considerations in mind you may observe
106that you could reorder the fields in the structure in order to place fields 115that you could reorder the fields in the structure in order to place fields
107where padding would otherwise be inserted, and hence reduce the overall 116where padding would otherwise be inserted, and hence reduce the overall
108resident memory size of structure instances. The optimal layout of the 117resident memory size of structure instances. The optimal layout of the
109above example is: 118above example is::
110 119
111 struct foo { 120 struct foo {
112 u32 field2; 121 u32 field2;
@@ -139,21 +148,21 @@ Code that causes unaligned access
139With the above in mind, let's move onto a real life example of a function 148With the above in mind, let's move onto a real life example of a function
140that can cause an unaligned memory access. The following function taken 149that can cause an unaligned memory access. The following function taken
141from include/linux/etherdevice.h is an optimized routine to compare two 150from include/linux/etherdevice.h is an optimized routine to compare two
142ethernet MAC addresses for equality. 151ethernet MAC addresses for equality::
143 152
144bool ether_addr_equal(const u8 *addr1, const u8 *addr2) 153 bool ether_addr_equal(const u8 *addr1, const u8 *addr2)
145{ 154 {
146#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 155 #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
147 u32 fold = ((*(const u32 *)addr1) ^ (*(const u32 *)addr2)) | 156 u32 fold = ((*(const u32 *)addr1) ^ (*(const u32 *)addr2)) |
148 ((*(const u16 *)(addr1 + 4)) ^ (*(const u16 *)(addr2 + 4))); 157 ((*(const u16 *)(addr1 + 4)) ^ (*(const u16 *)(addr2 + 4)));
149 158
150 return fold == 0; 159 return fold == 0;
151#else 160 #else
152 const u16 *a = (const u16 *)addr1; 161 const u16 *a = (const u16 *)addr1;
153 const u16 *b = (const u16 *)addr2; 162 const u16 *b = (const u16 *)addr2;
154 return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) == 0; 163 return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) == 0;
155#endif 164 #endif
156} 165 }
157 166
158In the above function, when the hardware has efficient unaligned access 167In the above function, when the hardware has efficient unaligned access
159capability, there is no issue with this code. But when the hardware isn't 168capability, there is no issue with this code. But when the hardware isn't
@@ -171,7 +180,8 @@ as it is a decent optimization for the cases when you can ensure alignment,
171which is true almost all of the time in ethernet networking context. 180which is true almost all of the time in ethernet networking context.
172 181
173 182
174Here is another example of some code that could cause unaligned accesses: 183Here is another example of some code that could cause unaligned accesses::
184
175 void myfunc(u8 *data, u32 value) 185 void myfunc(u8 *data, u32 value)
176 { 186 {
177 [...] 187 [...]
@@ -184,6 +194,7 @@ to an address that is not evenly divisible by 4.
184 194
185In summary, the 2 main scenarios where you may run into unaligned access 195In summary, the 2 main scenarios where you may run into unaligned access
186problems involve: 196problems involve:
197
187 1. Casting variables to types of different lengths 198 1. Casting variables to types of different lengths
188 2. Pointer arithmetic followed by access to at least 2 bytes of data 199 2. Pointer arithmetic followed by access to at least 2 bytes of data
189 200
@@ -195,7 +206,7 @@ The easiest way to avoid unaligned access is to use the get_unaligned() and
195put_unaligned() macros provided by the <asm/unaligned.h> header file. 206put_unaligned() macros provided by the <asm/unaligned.h> header file.
196 207
197Going back to an earlier example of code that potentially causes unaligned 208Going back to an earlier example of code that potentially causes unaligned
198access: 209access::
199 210
200 void myfunc(u8 *data, u32 value) 211 void myfunc(u8 *data, u32 value)
201 { 212 {
@@ -204,7 +215,7 @@ access:
204 [...] 215 [...]
205 } 216 }
206 217
207To avoid the unaligned memory access, you would rewrite it as follows: 218To avoid the unaligned memory access, you would rewrite it as follows::
208 219
209 void myfunc(u8 *data, u32 value) 220 void myfunc(u8 *data, u32 value)
210 { 221 {
@@ -215,7 +226,7 @@ To avoid the unaligned memory access, you would rewrite it as follows:
215 } 226 }
216 227
217The get_unaligned() macro works similarly. Assuming 'data' is a pointer to 228The get_unaligned() macro works similarly. Assuming 'data' is a pointer to
218memory and you wish to avoid unaligned access, its usage is as follows: 229memory and you wish to avoid unaligned access, its usage is as follows::
219 230
220 u32 value = get_unaligned((u32 *) data); 231 u32 value = get_unaligned((u32 *) data);
221 232
@@ -245,18 +256,10 @@ For some ethernet hardware that cannot DMA to unaligned addresses like
2454*n+2 or non-ethernet hardware, this can be a problem, and it is then 2564*n+2 or non-ethernet hardware, this can be a problem, and it is then
246required to copy the incoming frame into an aligned buffer. Because this is 257required to copy the incoming frame into an aligned buffer. Because this is
247unnecessary on architectures that can do unaligned accesses, the code can be 258unnecessary on architectures that can do unaligned accesses, the code can be
248made dependent on CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS like so: 259made dependent on CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS like so::
249
250#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
251 skb = original skb
252#else
253 skb = copy skb
254#endif
255
256--
257Authors: Daniel Drake <dsd@gentoo.org>,
258 Johannes Berg <johannes@sipsolutions.net>
259With help from: Alan Cox, Avuton Olrich, Heikki Orsila, Jan Engelhardt,
260Kyle McMartin, Kyle Moffett, Randy Dunlap, Robert Hancock, Uli Kunitz,
261Vadim Lobanov
262 260
261 #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
262 skb = original skb
263 #else
264 skb = copy skb
265 #endif