diff options
author | Mauro Carvalho Chehab <mchehab@s-opensource.com> | 2017-05-17 08:16:19 -0400 |
---|---|---|
committer | Jonathan Corbet <corbet@lwn.net> | 2017-07-14 15:58:09 -0400 |
commit | c6ebaf6bdb10469910afdcfc6af5c26846883e98 (patch) | |
tree | aa54085051f46e5c09bd114f63ffa853e797d949 | |
parent | 79ab3b0d21ea1ac48ce0e6b44997dd0a8c8f72e6 (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.txt | 57 |
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 | ========================= | ||
1 | UNALIGNED MEMORY ACCESSES | 2 | UNALIGNED 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 | |||
4 | Linux runs on a wide variety of architectures which have varying behaviour | 13 | Linux runs on a wide variety of architectures which have varying behaviour |
5 | when it comes to memory access. This document presents some details about | 14 | when it comes to memory access. This document presents some details about |
6 | unaligned accesses, why you need to write code that doesn't cause them, | 15 | unaligned accesses, why you need to write code that doesn't cause them, |
@@ -73,7 +82,7 @@ memory addresses of certain variables, etc. | |||
73 | 82 | ||
74 | Fortunately things are not too complex, as in most cases, the compiler | 83 | Fortunately things are not too complex, as in most cases, the compiler |
75 | ensures that things will work for you. For example, take the following | 84 | ensures that things will work for you. For example, take the following |
76 | structure: | 85 | structure:: |
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 | |||
106 | that you could reorder the fields in the structure in order to place fields | 115 | that you could reorder the fields in the structure in order to place fields |
107 | where padding would otherwise be inserted, and hence reduce the overall | 116 | where padding would otherwise be inserted, and hence reduce the overall |
108 | resident memory size of structure instances. The optimal layout of the | 117 | resident memory size of structure instances. The optimal layout of the |
109 | above example is: | 118 | above 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 | |||
139 | With the above in mind, let's move onto a real life example of a function | 148 | With the above in mind, let's move onto a real life example of a function |
140 | that can cause an unaligned memory access. The following function taken | 149 | that can cause an unaligned memory access. The following function taken |
141 | from include/linux/etherdevice.h is an optimized routine to compare two | 150 | from include/linux/etherdevice.h is an optimized routine to compare two |
142 | ethernet MAC addresses for equality. | 151 | ethernet MAC addresses for equality:: |
143 | 152 | ||
144 | bool 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 | ||
158 | In the above function, when the hardware has efficient unaligned access | 167 | In the above function, when the hardware has efficient unaligned access |
159 | capability, there is no issue with this code. But when the hardware isn't | 168 | capability, 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, | |||
171 | which is true almost all of the time in ethernet networking context. | 180 | which is true almost all of the time in ethernet networking context. |
172 | 181 | ||
173 | 182 | ||
174 | Here is another example of some code that could cause unaligned accesses: | 183 | Here 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 | ||
185 | In summary, the 2 main scenarios where you may run into unaligned access | 195 | In summary, the 2 main scenarios where you may run into unaligned access |
186 | problems involve: | 196 | problems 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 | |||
195 | put_unaligned() macros provided by the <asm/unaligned.h> header file. | 206 | put_unaligned() macros provided by the <asm/unaligned.h> header file. |
196 | 207 | ||
197 | Going back to an earlier example of code that potentially causes unaligned | 208 | Going back to an earlier example of code that potentially causes unaligned |
198 | access: | 209 | access:: |
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 | ||
207 | To avoid the unaligned memory access, you would rewrite it as follows: | 218 | To 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 | ||
217 | The get_unaligned() macro works similarly. Assuming 'data' is a pointer to | 228 | The get_unaligned() macro works similarly. Assuming 'data' is a pointer to |
218 | memory and you wish to avoid unaligned access, its usage is as follows: | 229 | memory 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 | |||
245 | 4*n+2 or non-ethernet hardware, this can be a problem, and it is then | 256 | 4*n+2 or non-ethernet hardware, this can be a problem, and it is then |
246 | required to copy the incoming frame into an aligned buffer. Because this is | 257 | required to copy the incoming frame into an aligned buffer. Because this is |
247 | unnecessary on architectures that can do unaligned accesses, the code can be | 258 | unnecessary on architectures that can do unaligned accesses, the code can be |
248 | made dependent on CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS like so: | 259 | made 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 | -- | ||
257 | Authors: Daniel Drake <dsd@gentoo.org>, | ||
258 | Johannes Berg <johannes@sipsolutions.net> | ||
259 | With help from: Alan Cox, Avuton Olrich, Heikki Orsila, Jan Engelhardt, | ||
260 | Kyle McMartin, Kyle Moffett, Randy Dunlap, Robert Hancock, Uli Kunitz, | ||
261 | Vadim Lobanov | ||
262 | 260 | ||
261 | #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS | ||
262 | skb = original skb | ||
263 | #else | ||
264 | skb = copy skb | ||
265 | #endif | ||