diff options
author | Mauro Carvalho Chehab <mchehab@s-opensource.com> | 2017-05-17 09:16:19 -0300 |
---|---|---|
committer | Jonathan Corbet <corbet@lwn.net> | 2017-07-14 13:58:09 -0600 |
commit | c6ebaf6bdb10469910afdcfc6af5c26846883e98 (patch) | |
tree | aa54085051f46e5c09bd114f63ffa853e797d949 /Documentation | |
parent | 79ab3b0d21ea1ac48ce0e6b44997dd0a8c8f72e6 (diff) | |
download | linux-c6ebaf6bdb10469910afdcfc6af5c26846883e98.tar.bz2 |
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>
Diffstat (limited to 'Documentation')
-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 @@ +========================= UNALIGNED MEMORY ACCESSES ========================= +:Author: Daniel Drake <dsd@gentoo.org>, +:Author: Johannes Berg <johannes@sipsolutions.net> + +:With help from: Alan Cox, Avuton Olrich, Heikki Orsila, Jan Engelhardt, + Kyle McMartin, Kyle Moffett, Randy Dunlap, Robert Hancock, Uli Kunitz, + Vadim Lobanov + + Linux runs on a wide variety of architectures which have varying behaviour when it comes to memory access. This document presents some details about unaligned accesses, why you need to write code that doesn't cause them, @@ -73,7 +82,7 @@ memory addresses of certain variables, etc. Fortunately things are not too complex, as in most cases, the compiler ensures that things will work for you. For example, take the following -structure: +structure:: struct foo { u16 field1; @@ -106,7 +115,7 @@ On a related topic, with the above considerations in mind you may observe that you could reorder the fields in the structure in order to place fields where padding would otherwise be inserted, and hence reduce the overall resident memory size of structure instances. The optimal layout of the -above example is: +above example is:: struct foo { u32 field2; @@ -139,21 +148,21 @@ Code that causes unaligned access With the above in mind, let's move onto a real life example of a function that can cause an unaligned memory access. The following function taken from include/linux/etherdevice.h is an optimized routine to compare two -ethernet MAC addresses for equality. +ethernet MAC addresses for equality:: -bool ether_addr_equal(const u8 *addr1, const u8 *addr2) -{ -#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + bool ether_addr_equal(const u8 *addr1, const u8 *addr2) + { + #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS u32 fold = ((*(const u32 *)addr1) ^ (*(const u32 *)addr2)) | ((*(const u16 *)(addr1 + 4)) ^ (*(const u16 *)(addr2 + 4))); return fold == 0; -#else + #else const u16 *a = (const u16 *)addr1; const u16 *b = (const u16 *)addr2; return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) == 0; -#endif -} + #endif + } In the above function, when the hardware has efficient unaligned access 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, which is true almost all of the time in ethernet networking context. -Here is another example of some code that could cause unaligned accesses: +Here is another example of some code that could cause unaligned accesses:: + void myfunc(u8 *data, u32 value) { [...] @@ -184,6 +194,7 @@ to an address that is not evenly divisible by 4. In summary, the 2 main scenarios where you may run into unaligned access problems involve: + 1. Casting variables to types of different lengths 2. Pointer arithmetic followed by access to at least 2 bytes of data @@ -195,7 +206,7 @@ The easiest way to avoid unaligned access is to use the get_unaligned() and put_unaligned() macros provided by the <asm/unaligned.h> header file. Going back to an earlier example of code that potentially causes unaligned -access: +access:: void myfunc(u8 *data, u32 value) { @@ -204,7 +215,7 @@ access: [...] } -To avoid the unaligned memory access, you would rewrite it as follows: +To avoid the unaligned memory access, you would rewrite it as follows:: void myfunc(u8 *data, u32 value) { @@ -215,7 +226,7 @@ To avoid the unaligned memory access, you would rewrite it as follows: } The get_unaligned() macro works similarly. Assuming 'data' is a pointer to -memory and you wish to avoid unaligned access, its usage is as follows: +memory and you wish to avoid unaligned access, its usage is as follows:: u32 value = get_unaligned((u32 *) data); @@ -245,18 +256,10 @@ For some ethernet hardware that cannot DMA to unaligned addresses like 4*n+2 or non-ethernet hardware, this can be a problem, and it is then required to copy the incoming frame into an aligned buffer. Because this is unnecessary on architectures that can do unaligned accesses, the code can be -made dependent on CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS like so: - -#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS - skb = original skb -#else - skb = copy skb -#endif - --- -Authors: Daniel Drake <dsd@gentoo.org>, - Johannes Berg <johannes@sipsolutions.net> -With help from: Alan Cox, Avuton Olrich, Heikki Orsila, Jan Engelhardt, -Kyle McMartin, Kyle Moffett, Randy Dunlap, Robert Hancock, Uli Kunitz, -Vadim Lobanov +made dependent on CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS like so:: + #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + skb = original skb + #else + skb = copy skb + #endif |