€•§‰Œsphinx.addnodes”Œdocument”“”)”}”(Œ rawsource”Œ”Œchildren”]”(Œ translations”Œ LanguagesNode”“”)”}”(hhh]”(hŒ pending_xref”“”)”}”(hhh]”Œdocutils.nodes”ŒText”“”ŒChinese (Simplified)”…””}”Œparent”hsbaŒ attributes”}”(Œids”]”Œclasses”]”Œnames”]”Œdupnames”]”Œbackrefs”]”Œ refdomain”Œstd”Œreftype”Œdoc”Œ reftarget”Œ4/translations/zh_CN/core-api/unaligned-memory-access”Œmodname”NŒ classname”NŒ refexplicit”ˆuŒtagname”hhh ubh)”}”(hhh]”hŒChinese (Traditional)”…””}”hh2sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ4/translations/zh_TW/core-api/unaligned-memory-access”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒItalian”…””}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ4/translations/it_IT/core-api/unaligned-memory-access”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒJapanese”…””}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ4/translations/ja_JP/core-api/unaligned-memory-access”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒKorean”…””}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ4/translations/ko_KR/core-api/unaligned-memory-access”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒSpanish”…””}”hh‚sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ4/translations/sp_SP/core-api/unaligned-memory-access”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubeh}”(h]”h ]”h"]”h$]”h&]”Œcurrent_language”ŒEnglish”uh1h hhŒ _document”hŒsource”NŒline”NubhŒsection”“”)”}”(hhh]”(hŒtitle”“”)”}”(hŒUnaligned Memory Accesses”h]”hŒUnaligned Memory Accesses”…””}”(hh¨hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hh£hžhhŸŒN/var/lib/git/docbuild/linux/Documentation/core-api/unaligned-memory-access.rst”h KubhŒ field_list”“”)”}”(hhh]”(hŒfield”“”)”}”(hhh]”(hŒ field_name”“”)”}”(hŒAuthor”h]”hŒAuthor”…””}”(hhÃhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÁhh¾hŸh¶h KubhŒ field_body”“”)”}”(hŒDaniel Drake ,”h]”hŒ paragraph”“”)”}”(hhÕh]”(hŒDaniel Drake <”…””}”(hhÙhžhhŸNh NubhŒ reference”“”)”}”(hŒdsd@gentoo.org”h]”hŒdsd@gentoo.org”…””}”(hhâhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”Œrefuri”Œmailto:dsd@gentoo.org”uh1hàhhÙubhŒ>,”…””}”(hhÙhžhhŸNh Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h KhhÓubah}”(h]”h ]”h"]”h$]”h&]”uh1hÑhh¾ubeh}”(h]”h ]”h"]”h$]”h&]”uh1h¼hŸh¶h Khh¹hžhubh½)”}”(hhh]”(hÂ)”}”(hŒAuthor”h]”hŒAuthor”…””}”(hj hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÁhjhŸh¶h KubhÒ)”}”(hŒ*Johannes Berg ”h]”hØ)”}”(hŒ)Johannes Berg ”h]”(hŒJohannes Berg <”…””}”(hjhžhhŸNh Nubhá)”}”(hŒjohannes@sipsolutions.net”h]”hŒjohannes@sipsolutions.net”…””}”(hj%hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”Œrefuri”Œ mailto:johannes@sipsolutions.net”uh1hàhjubhŒ>”…””}”(hjhžhhŸNh Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h Khjubah}”(h]”h ]”h"]”h$]”h&]”uh1hÑhjubeh}”(h]”h ]”h"]”h$]”h&]”uh1h¼hŸh¶h Khh¹hžhubh½)”}”(hhh]”(hÂ)”}”(hŒWith help from”h]”hŒWith help from”…””}”(hjNhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÁhjKhŸh¶h KubhÒ)”}”(hŒŽAlan Cox, Avuton Olrich, Heikki Orsila, Jan Engelhardt, Kyle McMartin, Kyle Moffett, Randy Dunlap, Robert Hancock, Uli Kunitz, Vadim Lobanov ”h]”hØ)”}”(hŒŒAlan Cox, Avuton Olrich, Heikki Orsila, Jan Engelhardt, Kyle McMartin, Kyle Moffett, Randy Dunlap, Robert Hancock, Uli Kunitz, Vadim Lobanov”h]”hŒŒAlan Cox, Avuton Olrich, Heikki Orsila, Jan Engelhardt, Kyle McMartin, Kyle Moffett, Randy Dunlap, Robert Hancock, Uli Kunitz, Vadim Lobanov”…””}”(hj`hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h Khj\ubah}”(h]”h ]”h"]”h$]”h&]”uh1hÑhjKubeh}”(h]”h ]”h"]”h$]”h&]”uh1h¼hŸh¶h Khh¹hžhubeh}”(h]”h ]”h"]”h$]”h&]”uh1h·hh£hžhhŸh¶h KubhØ)”}”(hŒø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, and how to write such code!”h]”hŒú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, and how to write such code!”…””}”(hj€hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h K hh£hžhubh¢)”}”(hhh]”(h§)”}”(hŒ%The definition of an unaligned access”h]”hŒ%The definition of an unaligned access”…””}”(hj‘hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hjŽhžhhŸh¶h KubhØ)”}”(hX.Unaligned memory accesses occur when you try to read N bytes of data starting from an address that is not evenly divisible by N (i.e. addr % N != 0). For example, reading 4 bytes of data from address 0x10004 is fine, but reading 4 bytes of data from address 0x10005 would be an unaligned memory access.”h]”hX.Unaligned memory accesses occur when you try to read N bytes of data starting from an address that is not evenly divisible by N (i.e. addr % N != 0). For example, reading 4 bytes of data from address 0x10004 is fine, but reading 4 bytes of data from address 0x10005 would be an unaligned memory access.”…””}”(hjŸhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h KhjŽhžhubhØ)”}”(hXªThe above may seem a little vague, as memory access can happen in different ways. The context here is at the machine code level: certain instructions read or write a number of bytes to or from memory (e.g. movb, movw, movl in x86 assembly). As will become clear, it is relatively easy to spot C statements which will compile to multiple-byte memory access instructions, namely when dealing with types such as u16, u32 and u64.”h]”hXªThe above may seem a little vague, as memory access can happen in different ways. The context here is at the machine code level: certain instructions read or write a number of bytes to or from memory (e.g. movb, movw, movl in x86 assembly). As will become clear, it is relatively easy to spot C statements which will compile to multiple-byte memory access instructions, namely when dealing with types such as u16, u32 and u64.”…””}”(hj­hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h KhjŽhžhubeh}”(h]”Œ%the-definition-of-an-unaligned-access”ah ]”h"]”Œ%the definition of an unaligned access”ah$]”h&]”uh1h¡hh£hžhhŸh¶h Kubh¢)”}”(hhh]”(h§)”}”(hŒNatural alignment”h]”hŒNatural alignment”…””}”(hjÆhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hjÃhžhhŸh¶h K%ubhØ)”}”(hŒ²The rule mentioned above forms what we refer to as natural alignment: When accessing N bytes of memory, the base memory address must be evenly divisible by N, i.e. addr % N == 0.”h]”hŒ²The rule mentioned above forms what we refer to as natural alignment: When accessing N bytes of memory, the base memory address must be evenly divisible by N, i.e. addr % N == 0.”…””}”(hjÔhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h K'hjÃhžhubhØ)”}”(hŒUWhen writing code, assume the target architecture has natural alignment requirements.”h]”hŒUWhen writing code, assume the target architecture has natural alignment requirements.”…””}”(hjâhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h K+hjÃhžhubhØ)”}”(hŒÿIn reality, only a few architectures require natural alignment on all sizes of memory access. However, we must consider ALL supported architectures; writing code that satisfies natural alignment requirements is the easiest way to achieve full portability.”h]”hŒÿIn reality, only a few architectures require natural alignment on all sizes of memory access. However, we must consider ALL supported architectures; writing code that satisfies natural alignment requirements is the easiest way to achieve full portability.”…””}”(hjðhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h K.hjÃhžhubeh}”(h]”Œnatural-alignment”ah ]”h"]”Œnatural alignment”ah$]”h&]”uh1h¡hh£hžhhŸh¶h K%ubh¢)”}”(hhh]”(h§)”}”(hŒWhy unaligned access is bad”h]”hŒWhy unaligned access is bad”…””}”(hj hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hjhžhhŸh¶h K5ubhØ)”}”(hŒÖThe effects of performing an unaligned memory access vary from architecture to architecture. It would be easy to write a whole document on the differences here; a summary of the common scenarios is presented below:”h]”hŒÖThe effects of performing an unaligned memory access vary from architecture to architecture. It would be easy to write a whole document on the differences here; a summary of the common scenarios is presented below:”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h K7hjhžhubhŒ block_quote”“”)”}”(hXÂ- Some architectures are able to perform unaligned memory accesses transparently, but there is usually a significant performance cost. - Some architectures raise processor exceptions when unaligned accesses happen. The exception handler is able to correct the unaligned access, at significant cost to performance. - Some architectures raise processor exceptions when unaligned accesses happen, but the exceptions do not contain enough information for the unaligned access to be corrected. - Some architectures are not capable of unaligned memory access, but will silently perform a different memory access to the one that was requested, resulting in a subtle code bug that is hard to detect! ”h]”hŒ bullet_list”“”)”}”(hhh]”(hŒ list_item”“”)”}”(hŒ„Some architectures are able to perform unaligned memory accesses transparently, but there is usually a significant performance cost.”h]”hØ)”}”(hŒ„Some architectures are able to perform unaligned memory accesses transparently, but there is usually a significant performance cost.”h]”hŒ„Some architectures are able to perform unaligned memory accesses transparently, but there is usually a significant performance cost.”…””}”(hj6hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h K;hj2ubah}”(h]”h ]”h"]”h$]”h&]”uh1j0hj-ubj1)”}”(hŒ°Some architectures raise processor exceptions when unaligned accesses happen. The exception handler is able to correct the unaligned access, at significant cost to performance.”h]”hØ)”}”(hŒ°Some architectures raise processor exceptions when unaligned accesses happen. The exception handler is able to correct the unaligned access, at significant cost to performance.”h]”hŒ°Some architectures raise processor exceptions when unaligned accesses happen. The exception handler is able to correct the unaligned access, at significant cost to performance.”…””}”(hjNhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h K=hjJubah}”(h]”h ]”h"]”h$]”h&]”uh1j0hj-ubj1)”}”(hŒ¬Some architectures raise processor exceptions when unaligned accesses happen, but the exceptions do not contain enough information for the unaligned access to be corrected.”h]”hØ)”}”(hŒ¬Some architectures raise processor exceptions when unaligned accesses happen, but the exceptions do not contain enough information for the unaligned access to be corrected.”h]”hŒ¬Some architectures raise processor exceptions when unaligned accesses happen, but the exceptions do not contain enough information for the unaligned access to be corrected.”…””}”(hjfhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h K@hjbubah}”(h]”h ]”h"]”h$]”h&]”uh1j0hj-ubj1)”}”(hŒÉSome architectures are not capable of unaligned memory access, but will silently perform a different memory access to the one that was requested, resulting in a subtle code bug that is hard to detect! ”h]”hØ)”}”(hŒÈSome architectures are not capable of unaligned memory access, but will silently perform a different memory access to the one that was requested, resulting in a subtle code bug that is hard to detect!”h]”hŒÈSome architectures are not capable of unaligned memory access, but will silently perform a different memory access to the one that was requested, resulting in a subtle code bug that is hard to detect!”…””}”(hj~hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h KChjzubah}”(h]”h ]”h"]”h$]”h&]”uh1j0hj-ubeh}”(h]”h ]”h"]”h$]”h&]”Œbullet”Œ-”uh1j+hŸh¶h K;hj'ubah}”(h]”h ]”h"]”h$]”h&]”uh1j%hŸh¶h K;hjhžhubhØ)”}”(hŒÇIt should be obvious from the above that if your code causes unaligned memory accesses to happen, your code will not work correctly on certain platforms and will cause performance problems on others.”h]”hŒÇIt should be obvious from the above that if your code causes unaligned memory accesses to happen, your code will not work correctly on certain platforms and will cause performance problems on others.”…””}”(hj hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h KGhjhžhubeh}”(h]”Œwhy-unaligned-access-is-bad”ah ]”h"]”Œwhy unaligned access is bad”ah$]”h&]”uh1h¡hh£hžhhŸh¶h K5ubh¢)”}”(hhh]”(h§)”}”(hŒ)Code that does not cause unaligned access”h]”hŒ)Code that does not cause unaligned access”…””}”(hj¹hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hj¶hžhhŸh¶h KMubhØ)”}”(hŒ»At first, the concepts above may seem a little hard to relate to actual coding practice. After all, you don't have a great deal of control over memory addresses of certain variables, etc.”h]”hŒ½At first, the concepts above may seem a little hard to relate to actual coding practice. After all, you don’t have a great deal of control over memory addresses of certain variables, etc.”…””}”(hjÇhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h KOhj¶hžhubhØ)”}”(hŒ™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::”h]”hŒ˜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:”…””}”(hjÕhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h KShj¶hžhubhŒ literal_block”“”)”}”(hŒJstruct foo { u16 field1; u32 field2; u8 field3; };”h]”hŒJstruct foo { u16 field1; u32 field2; u8 field3; };”…””}”hjåsbah}”(h]”h ]”h"]”h$]”h&]”Œ xml:space”Œpreserve”uh1jãhŸh¶h KWhj¶hžhubhØ)”}”(hX¨Let us assume that an instance of the above structure resides in memory starting at address 0x10000. With a basic level of understanding, it would not be unreasonable to expect that accessing field2 would cause an unaligned access. You'd be expecting field2 to be located at offset 2 bytes into the structure, i.e. address 0x10002, but that address is not evenly divisible by 4 (remember, we're reading a 4 byte value here).”h]”hX¬Let us assume that an instance of the above structure resides in memory starting at address 0x10000. With a basic level of understanding, it would not be unreasonable to expect that accessing field2 would cause an unaligned access. You’d be expecting field2 to be located at offset 2 bytes into the structure, i.e. address 0x10002, but that address is not evenly divisible by 4 (remember, we’re reading a 4 byte value here).”…””}”(hjõhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h K]hj¶hžhubhØ)”}”(hXhFortunately, the compiler understands the alignment constraints, so in the above case it would insert 2 bytes of padding in between field1 and field2. Therefore, for standard structure types you can always rely on the compiler to pad structures so that accesses to fields are suitably aligned (assuming you do not cast the field to a type of different length).”h]”hXhFortunately, the compiler understands the alignment constraints, so in the above case it would insert 2 bytes of padding in between field1 and field2. Therefore, for standard structure types you can always rely on the compiler to pad structures so that accesses to fields are suitably aligned (assuming you do not cast the field to a type of different length).”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h Kdhj¶hžhubhØ)”}”(hŒ¥Similarly, you can also rely on the compiler to align variables and function parameters to a naturally aligned scheme, based on the size of the type of the variable.”h]”hŒ¥Similarly, you can also rely on the compiler to align variables and function parameters to a naturally aligned scheme, based on the size of the type of the variable.”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h Kjhj¶hžhubhØ)”}”(hŒ«At this point, it should be clear that accessing a single byte (u8 or char) will never cause an unaligned access, because all memory addresses are evenly divisible by one.”h]”hŒ«At this point, it should be clear that accessing a single byte (u8 or char) will never cause an unaligned access, because all memory addresses are evenly divisible by one.”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h Knhj¶hžhubhØ)”}”(hX7On 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::”h]”hX6On 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:”…””}”(hj-hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h Krhj¶hžhubjä)”}”(hŒJstruct foo { u32 field2; u16 field1; u8 field3; };”h]”hŒJstruct foo { u32 field2; u16 field1; u8 field3; };”…””}”hj;sbah}”(h]”h ]”h"]”h$]”h&]”jójôuh1jãhŸh¶h Kxhj¶hžhubhØ)”}”(hŒÙFor a natural alignment scheme, the compiler would only have to add a single byte of padding at the end of the structure. This padding is added in order to satisfy alignment constraints for arrays of these structures.”h]”hŒÙFor a natural alignment scheme, the compiler would only have to add a single byte of padding at the end of the structure. This padding is added in order to satisfy alignment constraints for arrays of these structures.”…””}”(hjIhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h K~hj¶hžhubhØ)”}”(hX'Another point worth mentioning is the use of __attribute__((packed)) on a structure type. This GCC-specific attribute tells the compiler never to insert any padding within structures, useful when you want to use a C struct to represent some data that comes in a fixed arrangement 'off the wire'.”h]”hX+Another point worth mentioning is the use of __attribute__((packed)) on a structure type. This GCC-specific attribute tells the compiler never to insert any padding within structures, useful when you want to use a C struct to represent some data that comes in a fixed arrangement ‘off the wire’.”…””}”(hjWhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h K‚hj¶hžhubhØ)”}”(hX.You might be inclined to believe that usage of this attribute can easily lead to unaligned accesses when accessing fields that do not satisfy architectural alignment requirements. However, again, the compiler is aware of the alignment constraints and will generate extra instructions to perform the memory access in a way that does not cause unaligned access. Of course, the extra instructions obviously cause a loss in performance compared to the non-packed case, so the packed attribute should only be used when avoiding structure padding is of importance.”h]”hX.You might be inclined to believe that usage of this attribute can easily lead to unaligned accesses when accessing fields that do not satisfy architectural alignment requirements. However, again, the compiler is aware of the alignment constraints and will generate extra instructions to perform the memory access in a way that does not cause unaligned access. Of course, the extra instructions obviously cause a loss in performance compared to the non-packed case, so the packed attribute should only be used when avoiding structure padding is of importance.”…””}”(hjehžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h K‡hj¶hžhubeh}”(h]”Œ)code-that-does-not-cause-unaligned-access”ah ]”h"]”Œ)code that does not cause unaligned access”ah$]”h&]”uh1h¡hh£hžhhŸh¶h KMubh¢)”}”(hhh]”(h§)”}”(hŒ!Code that causes unaligned access”h]”hŒ!Code that causes unaligned access”…””}”(hj~hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hj{hžhhŸh¶h K’ubhØ)”}”(hŒÿ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::”h]”hXWith 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:”…””}”(hjŒhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h K”hj{hžhubjä)”}”(hXµ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 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 }”h]”hXµ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 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 }”…””}”hjšsbah}”(h]”h ]”h"]”h$]”h&]”jójôuh1jãhŸh¶h K™hj{hžhubhØ)”}”(hX"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 able to access memory on arbitrary boundaries, the reference to a[0] causes 2 bytes (16 bits) to be read from memory starting at address addr1.”h]”hX$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 able to access memory on arbitrary boundaries, the reference to a[0] causes 2 bytes (16 bits) to be read from memory starting at address addr1.”…””}”(hj¨hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h K§hj{hžhubhØ)”}”(hŒoThink about what would happen if addr1 was an odd address such as 0x10003. (Hint: it'd be an unaligned access.)”h]”hŒqThink about what would happen if addr1 was an odd address such as 0x10003. (Hint: it’d be an unaligned access.)”…””}”(hj¶hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h K¬hj{hžhubhØ)”}”(hXÂDespite the potential unaligned access problems with the above function, it is included in the kernel anyway but is understood to only work normally on 16-bit-aligned addresses. It is up to the caller to ensure this alignment or not use this function at all. This alignment-unsafe function is still useful 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.”h]”hXÂDespite the potential unaligned access problems with the above function, it is included in the kernel anyway but is understood to only work normally on 16-bit-aligned addresses. It is up to the caller to ensure this alignment or not use this function at all. This alignment-unsafe function is still useful 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.”…””}”(hjÄhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h K¯hj{hžhubhØ)”}”(hŒJHere is another example of some code that could cause unaligned accesses::”h]”hŒIHere is another example of some code that could cause unaligned accesses:”…””}”(hjÒhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h K·hj{hžhubjä)”}”(hŒnvoid myfunc(u8 *data, u32 value) { [...] *((u32 *) data) = cpu_to_le32(value); [...] }”h]”hŒnvoid myfunc(u8 *data, u32 value) { [...] *((u32 *) data) = cpu_to_le32(value); [...] }”…””}”hjàsbah}”(h]”h ]”h"]”h$]”h&]”jójôuh1jãhŸh¶h K¹hj{hžhubhØ)”}”(hŒ}This code will cause unaligned accesses every time the data parameter points to an address that is not evenly divisible by 4.”h]”hŒ}This code will cause unaligned accesses every time the data parameter points to an address that is not evenly divisible by 4.”…””}”(hjîhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h KÀhj{hžhubhØ)”}”(hŒZIn summary, the 2 main scenarios where you may run into unaligned access problems involve:”h]”hŒZIn summary, the 2 main scenarios where you may run into unaligned access problems involve:”…””}”(hjühžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h KÃhj{hžhubj&)”}”(hŒy1. Casting variables to types of different lengths 2. Pointer arithmetic followed by access to at least 2 bytes of data ”h]”hŒenumerated_list”“”)”}”(hhh]”(j1)”}”(hŒ/Casting variables to types of different lengths”h]”hØ)”}”(hjh]”hŒ/Casting variables to types of different lengths”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h KÆhjubah}”(h]”h ]”h"]”h$]”h&]”uh1j0hjubj1)”}”(hŒCPointer arithmetic followed by access to at least 2 bytes of data ”h]”hØ)”}”(hŒAPointer arithmetic followed by access to at least 2 bytes of data”h]”hŒAPointer arithmetic followed by access to at least 2 bytes of data”…””}”(hj.hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h KÇhj*ubah}”(h]”h ]”h"]”h$]”h&]”uh1j0hjubeh}”(h]”h ]”h"]”h$]”h&]”Œenumtype”Œarabic”Œprefix”hŒsuffix”Œ.”uh1jhj ubah}”(h]”h ]”h"]”h$]”h&]”uh1j%hŸh¶h KÆhj{hžhubeh}”(h]”Œ!code-that-causes-unaligned-access”ah ]”h"]”Œ!code that causes unaligned access”ah$]”h&]”uh1h¡hh£hžhhŸh¶h K’ubh¢)”}”(hhh]”(h§)”}”(hŒAvoiding unaligned accesses”h]”hŒAvoiding unaligned accesses”…””}”(hj^hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hj[hžhhŸh¶h KËubhØ)”}”(hŒ“The easiest way to avoid unaligned access is to use the get_unaligned() and put_unaligned() macros provided by the header file.”h]”hŒ“The easiest way to avoid unaligned access is to use the get_unaligned() and put_unaligned() macros provided by the header file.”…””}”(hjlhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h KÍhj[hžhubhØ)”}”(hŒSGoing back to an earlier example of code that potentially causes unaligned access::”h]”hŒRGoing back to an earlier example of code that potentially causes unaligned access:”…””}”(hjzhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h KÐhj[hžhubjä)”}”(hŒnvoid myfunc(u8 *data, u32 value) { [...] *((u32 *) data) = cpu_to_le32(value); [...] }”h]”hŒnvoid myfunc(u8 *data, u32 value) { [...] *((u32 *) data) = cpu_to_le32(value); [...] }”…””}”hjˆsbah}”(h]”h ]”h"]”h$]”h&]”jójôuh1jãhŸh¶h KÓhj[hžhubhØ)”}”(hŒGTo avoid the unaligned memory access, you would rewrite it as follows::”h]”hŒFTo avoid the unaligned memory access, you would rewrite it as follows:”…””}”(hj–hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h KÚhj[hžhubjä)”}”(hŒvoid myfunc(u8 *data, u32 value) { [...] value = cpu_to_le32(value); put_unaligned(value, (u32 *) data); [...] }”h]”hŒvoid myfunc(u8 *data, u32 value) { [...] value = cpu_to_le32(value); put_unaligned(value, (u32 *) data); [...] }”…””}”hj¤sbah}”(h]”h ]”h"]”h$]”h&]”jójôuh1jãhŸh¶h KÜhj[hžhubhØ)”}”(hŒ“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::”h]”hŒ–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:”…””}”(hj²hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h Kähj[hžhubjä)”}”(hŒ(u32 value = get_unaligned((u32 *) data);”h]”hŒ(u32 value = get_unaligned((u32 *) data);”…””}”hjÀsbah}”(h]”h ]”h"]”h$]”h&]”jójôuh1jãhŸh¶h Kçhj[hžhubhØ)”}”(hŒ÷These macros work for memory accesses of any length (not just 32 bits as in the examples above). Be aware that when compared to standard access of aligned memory, using these macros to access unaligned memory can be costly in terms of performance.”h]”hŒ÷These macros work for memory accesses of any length (not just 32 bits as in the examples above). Be aware that when compared to standard access of aligned memory, using these macros to access unaligned memory can be costly in terms of performance.”…””}”(hjÎhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h Kéhj[hžhubhØ)”}”(hŒçIf use of such macros is not convenient, another option is to use memcpy(), where the source or destination (or both) are of type u8* or unsigned char*. Due to the byte-wise nature of this operation, unaligned accesses are avoided.”h]”hŒçIf use of such macros is not convenient, another option is to use memcpy(), where the source or destination (or both) are of type u8* or unsigned char*. Due to the byte-wise nature of this operation, unaligned accesses are avoided.”…””}”(hjÜhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h Kîhj[hžhubeh}”(h]”Œavoiding-unaligned-accesses”ah ]”h"]”Œavoiding unaligned accesses”ah$]”h&]”uh1h¡hh£hžhhŸh¶h KËubh¢)”}”(hhh]”(h§)”}”(hŒAlignment vs. Networking”h]”hŒAlignment vs. Networking”…””}”(hjõhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hjòhžhhŸh¶h KôubhØ)”}”(hXGOn architectures that require aligned loads, networking requires that the IP header is aligned on a four-byte boundary to optimise the IP stack. For regular ethernet hardware, the constant NET_IP_ALIGN is used. On most architectures this constant has the value 2 because the normal ethernet header is 14 bytes long, so in order to get proper alignment one needs to DMA to an address which can be expressed as 4*n + 2. One notable exception here is powerpc which defines NET_IP_ALIGN to 0 because DMA to unaligned addresses can be very expensive and dwarf the cost of unaligned loads.”h]”hXGOn architectures that require aligned loads, networking requires that the IP header is aligned on a four-byte boundary to optimise the IP stack. For regular ethernet hardware, the constant NET_IP_ALIGN is used. On most architectures this constant has the value 2 because the normal ethernet header is 14 bytes long, so in order to get proper alignment one needs to DMA to an address which can be expressed as 4*n + 2. One notable exception here is powerpc which defines NET_IP_ALIGN to 0 because DMA to unaligned addresses can be very expensive and dwarf the cost of unaligned loads.”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h KöhjòhžhubhØ)”}”(hXhFor 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::”h]”hXgFor 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:”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h Kÿhjòhžhubjä)”}”(hŒl#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS skb = original skb #else skb = copy skb #endif”h]”hŒl#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS skb = original skb #else skb = copy skb #endif”…””}”hjsbah}”(h]”h ]”h"]”h$]”h&]”jójôuh1jãhŸh¶h Mhjòhžhubeh}”(h]”Œalignment-vs-networking”ah ]”h"]”Œalignment vs. networking”ah$]”h&]”uh1h¡hh£hžhhŸh¶h Kôubeh}”(h]”Œunaligned-memory-accesses”ah ]”h"]”Œunaligned memory accesses”ah$]”h&]”uh1h¡hhhžhhŸh¶h Kubeh}”(h]”h ]”h"]”h$]”h&]”Œsource”h¶uh1hŒcurrent_source”NŒ current_line”NŒsettings”Œdocutils.frontend”ŒValues”“”)”}”(h¦NŒ generator”NŒ datestamp”NŒ source_link”NŒ source_url”NŒ toc_backlinks”Œentry”Œfootnote_backlinks”KŒ sectnum_xform”KŒstrip_comments”NŒstrip_elements_with_classes”NŒ strip_classes”NŒ report_level”KŒ halt_level”KŒexit_status_level”KŒdebug”NŒwarning_stream”NŒ traceback”ˆŒinput_encoding”Œ utf-8-sig”Œinput_encoding_error_handler”Œstrict”Œoutput_encoding”Œutf-8”Œoutput_encoding_error_handler”j`Œerror_encoding”Œutf-8”Œerror_encoding_error_handler”Œbackslashreplace”Œ language_code”Œen”Œrecord_dependencies”NŒconfig”NŒ id_prefix”hŒauto_id_prefix”Œid”Œ dump_settings”NŒdump_internals”NŒdump_transforms”NŒdump_pseudo_xml”NŒexpose_internals”NŒstrict_visitor”NŒ_disable_config”NŒ_source”h¶Œ _destination”NŒ _config_files”]”Œ7/var/lib/git/docbuild/linux/Documentation/docutils.conf”aŒfile_insertion_enabled”ˆŒ raw_enabled”KŒline_length_limit”M'Œpep_references”NŒ pep_base_url”Œhttps://peps.python.org/”Œpep_file_url_template”Œpep-%04d”Œrfc_references”NŒ rfc_base_url”Œ&https://datatracker.ietf.org/doc/html/”Œ tab_width”KŒtrim_footnote_reference_space”‰Œsyntax_highlight”Œlong”Œ smart_quotes”ˆŒsmartquotes_locales”]”Œcharacter_level_inline_markup”‰Œdoctitle_xform”‰Œ docinfo_xform”KŒsectsubtitle_xform”‰Œ image_loading”Œlink”Œembed_stylesheet”‰Œcloak_email_addresses”ˆŒsection_self_link”‰Œenv”NubŒreporter”NŒindirect_targets”]”Œsubstitution_defs”}”Œsubstitution_names”}”Œrefnames”}”Œrefids”}”Œnameids”}”(j:j7jÀj½jjj³j°jxjujXjUjïjìj2j/uŒ nametypes”}”(j:‰jÀ‰j‰j³‰jx‰jX‰jï‰j2‰uh}”(j7h£j½jŽjjÃj°jjuj¶jUj{jìj[j/jòuŒ footnote_refs”}”Œ citation_refs”}”Œ autofootnotes”]”Œautofootnote_refs”]”Œsymbol_footnotes”]”Œsymbol_footnote_refs”]”Œ footnotes”]”Œ citations”]”Œautofootnote_start”KŒsymbol_footnote_start”KŒ id_counter”Œ collections”ŒCounter”“”}”…”R”Œparse_messages”]”Œtransform_messages”]”Œ transformer”NŒ include_log”]”Œ decoration”Nhžhub.