mhsphinx.addnodesdocument)}( rawsourcechildren]( translations LanguagesNode)}(hhh](h pending_xref)}(hhh]docutils.nodesTextChinese (Simplified)}(hhparenthuba attributes}(ids]classes]names]dupnames]backrefs] refdomainstdreftypedoc reftarget$/translations/zh_CN/core-api/packingmodnameN classnameN refexplicitutagnamehhh ubh)}(hhh]hChinese (Traditional)}(hhhh2ubah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget$/translations/zh_TW/core-api/packingmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hItalian}(hhhhFubah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget$/translations/it_IT/core-api/packingmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hJapanese}(hhhhZubah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget$/translations/ja_JP/core-api/packingmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hKorean}(hhhhnubah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget$/translations/ko_KR/core-api/packingmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hSpanish}(hhhhubah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget$/translations/sp_SP/core-api/packingmodnameN classnameN refexplicituh1hhh ubeh}(h]h ]h"]h$]h&]current_languageEnglishuh1h hh _documenthsourceNlineNubhsection)}(hhh](htitle)}(h0Generic bitfield packing and unpacking functionsh]h0Generic bitfield packing and unpacking functions}(hhhhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhhh>/var/lib/git/docbuild/linux/Documentation/core-api/packing.rsthKubh)}(hhh](h)}(hProblem statementh]hProblem statement}(hhhhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhhhhhKubh paragraph)}(hXWhen working with hardware, one has to choose between several approaches of interfacing with it. One can memory-map a pointer to a carefully crafted struct over the hardware device's memory region, and access its fields as struct members (potentially declared as bitfields). But writing code this way would make it less portable, due to potential endianness mismatches between the CPU and the hardware device. Additionally, one has to pay close attention when translating register definitions from the hardware documentation into bit field indices for the structs. Also, some hardware (typically networking equipment) tends to group its register fields in ways that violate any reasonable word boundaries (sometimes even 64 bit ones). This creates the inconvenience of having to define "high" and "low" portions of register fields within the struct. A more robust alternative to struct field definitions would be to extract the required fields by shifting the appropriate number of bits. But this would still not protect from endianness mismatches, except if all memory accesses were performed byte-by-byte. Also the code can easily get cluttered, and the high-level idea might get lost among the many bit shifts required. Many drivers take the bit-shifting approach and then attempt to reduce the clutter with tailored macros, but more often than not these macros take shortcuts that still prevent the code from being truly portable.h]hXWhen working with hardware, one has to choose between several approaches of interfacing with it. One can memory-map a pointer to a carefully crafted struct over the hardware device’s memory region, and access its fields as struct members (potentially declared as bitfields). But writing code this way would make it less portable, due to potential endianness mismatches between the CPU and the hardware device. Additionally, one has to pay close attention when translating register definitions from the hardware documentation into bit field indices for the structs. Also, some hardware (typically networking equipment) tends to group its register fields in ways that violate any reasonable word boundaries (sometimes even 64 bit ones). This creates the inconvenience of having to define “high” and “low” portions of register fields within the struct. A more robust alternative to struct field definitions would be to extract the required fields by shifting the appropriate number of bits. But this would still not protect from endianness mismatches, except if all memory accesses were performed byte-by-byte. Also the code can easily get cluttered, and the high-level idea might get lost among the many bit shifts required. Many drivers take the bit-shifting approach and then attempt to reduce the clutter with tailored macros, but more often than not these macros take shortcuts that still prevent the code from being truly portable.}(hhhhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubeh}(h]problem-statementah ]h"]problem statementah$]h&]uh1hhhhhhhhKubh)}(hhh](h)}(h The solutionh]h The solution}(hhhhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhhhhhKubh)}(h'This API deals with 2 basic operations:h]h'This API deals with 2 basic operations:}(hhhhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK hhhhubh block_quote)}(hhh]h bullet_list)}(hhh](h list_item)}(hSPacking a CPU-usable number into a memory buffer (with hardware constraints/quirks)h]h)}(hSPacking a CPU-usable number into a memory buffer (with hardware constraints/quirks)h]hSPacking a CPU-usable number into a memory buffer (with hardware constraints/quirks)}(hjhjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK"hj ubah}(h]h ]h"]h$]h&]uh1j hjubj )}(h\Unpacking a memory buffer (which has hardware constraints/quirks) into a CPU-usable number. h]h)}(h[Unpacking a memory buffer (which has hardware constraints/quirks) into a CPU-usable number.h]h[Unpacking a memory buffer (which has hardware constraints/quirks) into a CPU-usable number.}(hj)hj'hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK$hj#ubah}(h]h ]h"]h$]h&]uh1j hjubeh}(h]h ]h"]h$]h&]bullet-uh1jhhhK"hjubah}(h]h ]h"]h$]h&]uh1hhhhhhNhNubh)}(hThe API offers an abstraction over said hardware constraints and quirks, over CPU endianness and therefore between possible mismatches between the two.h]hThe API offers an abstraction over said hardware constraints and quirks, over CPU endianness and therefore between possible mismatches between the two.}(hjKhjIhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK'hhhhubh)}(hThe basic unit of these API functions is the u64. From the CPU's perspective, bit 63 always means bit offset 7 of byte 7, albeit only logically. The question is: where do we lay this bit out in memory?h]hThe basic unit of these API functions is the u64. From the CPU’s perspective, bit 63 always means bit offset 7 of byte 7, albeit only logically. The question is: where do we lay this bit out in memory?}(hjYhjWhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK+hhhhubh)}(hThe following examples cover the memory layout of a packed u64 field. The byte offsets in the packed buffer are always implicitly 0, 1, ... 7. What the examples show is where the logical bytes and bits sit.h]hThe following examples cover the memory layout of a packed u64 field. The byte offsets in the packed buffer are always implicitly 0, 1, ... 7. What the examples show is where the logical bytes and bits sit.}(hjghjehhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK/hhhhubhenumerated_list)}(hhh]j )}(h0Normally (no quirks), we would do it like this: h]h)}(h/Normally (no quirks), we would do it like this:h]h/Normally (no quirks), we would do it like this:}(hj~hj|hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK3hjxubah}(h]h ]h"]h$]h&]uh1j hjuhhhhhNubah}(h]h ]h"]h$]h&]enumtypearabicprefixhsuffix.uh1jshhhhhhhK3ubh literal_block)}(hXU63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 7 6 5 4 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 3 2 1 0h]hXU63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 7 6 5 4 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 3 2 1 0}(hhhjubah}(h]h ]h"]h$]h&] xml:spacepreserveuh1jhhhK7hhhhubh)}(hX2That is, the MSByte (7) of the CPU-usable u64 sits at memory offset 0, and the LSByte (0) of the u64 sits at memory offset 7. This corresponds to what most folks would regard to as "big endian", where bit i corresponds to the number 2^i. This is also referred to in the code comments as "logical" notation.h]hX:That is, the MSByte (7) of the CPU-usable u64 sits at memory offset 0, and the LSByte (0) of the u64 sits at memory offset 7. This corresponds to what most folks would regard to as “big endian”, where bit i corresponds to the number 2^i. This is also referred to in the code comments as “logical” notation.}(hjhjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKEnumerated list start value not ordinal-1: “2” (ordinal 2)}(hhhj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj ubah}(h]h ]h"]h$]h&]levelKtypeINFOsourcehlineKuh1jhhhhhhhKCubj )}(hhh]h)}(h:Enumerated list start value not ordinal-1: "3" (ordinal 3)h]h>Enumerated list start value not ordinal-1: “3” (ordinal 3)}(hhhj)hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj&ubah}(h]h ]h"]h$]h&]levelKtypej#sourcehlineKuh1jhhhhhhhKPubj )}(hhh]h)}(h:Enumerated list start value not ordinal-1: "4" (ordinal 4)h]h>Enumerated list start value not ordinal-1: “4” (ordinal 4)}(hhhjDhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjAubah}(h]h ]h"]h$]h&]levelKtypej#sourcehlineKuh1jhhhhhhhK]ubj )}(hhh]h)}(h:Enumerated list start value not ordinal-1: "5" (ordinal 5)h]h>Enumerated list start value not ordinal-1: “5” (ordinal 5)}(hhhj_hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj\ubah}(h]h ]h"]h$]h&]levelKtypej#sourcehlineKuh1jhhhhhhhKhubj )}(hhh]h)}(h:Enumerated list start value not ordinal-1: "6" (ordinal 6)h]h>Enumerated list start value not ordinal-1: “6” (ordinal 6)}(hhhjzhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjwubah}(h]h ]h"]h$]h&]levelKtypej#sourcehlineKuh1jhhhhhhhKvubj )}(hhh]h)}(h:Enumerated list start value not ordinal-1: "7" (ordinal 7)h]h>Enumerated list start value not ordinal-1: “7” (ordinal 7)}(hhhjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjubah}(h]h ]h"]h$]h&]levelKtypej#sourcehlineKuh1jhhhhhhhKubj )}(hhh]h)}(h:Enumerated list start value not ordinal-1: "8" (ordinal 8)h]h>Enumerated list start value not ordinal-1: “8” (ordinal 8)}(hhhjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjubah}(h]h ]h"]h$]h&]levelKtypej#sourcehlineKuh1jhhhhhhhKubetransform_messages] transformerN include_log] decorationNhhub.