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 | ||
