~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/Documentation/core-api/packing.rst

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 ================================================
  2 Generic bitfield packing and unpacking functions
  3 ================================================
  4 
  5 Problem statement
  6 -----------------
  7 
  8 When working with hardware, one has to choose between several approaches of
  9 interfacing with it.
 10 One can memory-map a pointer to a carefully crafted struct over the hardware
 11 device's memory region, and access its fields as struct members (potentially
 12 declared as bitfields). But writing code this way would make it less portable,
 13 due to potential endianness mismatches between the CPU and the hardware device.
 14 Additionally, one has to pay close attention when translating register
 15 definitions from the hardware documentation into bit field indices for the
 16 structs. Also, some hardware (typically networking equipment) tends to group
 17 its register fields in ways that violate any reasonable word boundaries
 18 (sometimes even 64 bit ones). This creates the inconvenience of having to
 19 define "high" and "low" portions of register fields within the struct.
 20 A more robust alternative to struct field definitions would be to extract the
 21 required fields by shifting the appropriate number of bits. But this would
 22 still not protect from endianness mismatches, except if all memory accesses
 23 were performed byte-by-byte. Also the code can easily get cluttered, and the
 24 high-level idea might get lost among the many bit shifts required.
 25 Many drivers take the bit-shifting approach and then attempt to reduce the
 26 clutter with tailored macros, but more often than not these macros take
 27 shortcuts that still prevent the code from being truly portable.
 28 
 29 The solution
 30 ------------
 31 
 32 This API deals with 2 basic operations:
 33 
 34   - Packing a CPU-usable number into a memory buffer (with hardware
 35     constraints/quirks)
 36   - Unpacking a memory buffer (which has hardware constraints/quirks)
 37     into a CPU-usable number.
 38 
 39 The API offers an abstraction over said hardware constraints and quirks,
 40 over CPU endianness and therefore between possible mismatches between
 41 the two.
 42 
 43 The basic unit of these API functions is the u64. From the CPU's
 44 perspective, bit 63 always means bit offset 7 of byte 7, albeit only
 45 logically. The question is: where do we lay this bit out in memory?
 46 
 47 The following examples cover the memory layout of a packed u64 field.
 48 The byte offsets in the packed buffer are always implicitly 0, 1, ... 7.
 49 What the examples show is where the logical bytes and bits sit.
 50 
 51 1. Normally (no quirks), we would do it like this:
 52 
 53 ::
 54 
 55   63 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
 56   7                       6                       5                        4
 57   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
 58   3                       2                       1                        0
 59 
 60 That is, the MSByte (7) of the CPU-usable u64 sits at memory offset 0, and the
 61 LSByte (0) of the u64 sits at memory offset 7.
 62 This corresponds to what most folks would regard to as "big endian", where
 63 bit i corresponds to the number 2^i. This is also referred to in the code
 64 comments as "logical" notation.
 65 
 66 
 67 2. If QUIRK_MSB_ON_THE_RIGHT is set, we do it like this:
 68 
 69 ::
 70 
 71   56 57 58 59 60 61 62 63 48 49 50 51 52 53 54 55 40 41 42 43 44 45 46 47 32 33 34 35 36 37 38 39
 72   7                       6                        5                       4
 73   24 25 26 27 28 29 30 31 16 17 18 19 20 21 22 23  8  9 10 11 12 13 14 15  0  1  2  3  4  5  6  7
 74   3                       2                        1                       0
 75 
 76 That is, QUIRK_MSB_ON_THE_RIGHT does not affect byte positioning, but
 77 inverts bit offsets inside a byte.
 78 
 79 
 80 3. If QUIRK_LITTLE_ENDIAN is set, we do it like this:
 81 
 82 ::
 83 
 84   39 38 37 36 35 34 33 32 47 46 45 44 43 42 41 40 55 54 53 52 51 50 49 48 63 62 61 60 59 58 57 56
 85   4                       5                       6                       7
 86   7  6  5  4  3  2  1  0  15 14 13 12 11 10  9  8 23 22 21 20 19 18 17 16 31 30 29 28 27 26 25 24
 87   0                       1                       2                       3
 88 
 89 Therefore, QUIRK_LITTLE_ENDIAN means that inside the memory region, every
 90 byte from each 4-byte word is placed at its mirrored position compared to
 91 the boundary of that word.
 92 
 93 4. If QUIRK_MSB_ON_THE_RIGHT and QUIRK_LITTLE_ENDIAN are both set, we do it
 94    like this:
 95 
 96 ::
 97 
 98   32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
 99   4                       5                       6                       7
100   0  1  2  3  4  5  6  7  8   9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
101   0                       1                       2                       3
102 
103 
104 5. If just QUIRK_LSW32_IS_FIRST is set, we do it like this:
105 
106 ::
107 
108   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
109   3                       2                       1                        0
110   63 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
111   7                       6                       5                        4
112 
113 In this case the 8 byte memory region is interpreted as follows: first
114 4 bytes correspond to the least significant 4-byte word, next 4 bytes to
115 the more significant 4-byte word.
116 
117 
118 6. If QUIRK_LSW32_IS_FIRST and QUIRK_MSB_ON_THE_RIGHT are set, we do it like
119    this:
120 
121 ::
122 
123   24 25 26 27 28 29 30 31 16 17 18 19 20 21 22 23  8  9 10 11 12 13 14 15  0  1  2  3  4  5  6  7
124   3                       2                        1                       0
125   56 57 58 59 60 61 62 63 48 49 50 51 52 53 54 55 40 41 42 43 44 45 46 47 32 33 34 35 36 37 38 39
126   7                       6                        5                       4
127 
128 
129 7. If QUIRK_LSW32_IS_FIRST and QUIRK_LITTLE_ENDIAN are set, it looks like
130    this:
131 
132 ::
133 
134   7  6  5  4  3  2  1  0  15 14 13 12 11 10  9  8 23 22 21 20 19 18 17 16 31 30 29 28 27 26 25 24
135   0                       1                       2                       3
136   39 38 37 36 35 34 33 32 47 46 45 44 43 42 41 40 55 54 53 52 51 50 49 48 63 62 61 60 59 58 57 56
137   4                       5                       6                       7
138 
139 
140 8. If QUIRK_LSW32_IS_FIRST, QUIRK_LITTLE_ENDIAN and QUIRK_MSB_ON_THE_RIGHT
141    are set, it looks like this:
142 
143 ::
144 
145   0  1  2  3  4  5  6  7  8   9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
146   0                       1                       2                       3
147   32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
148   4                       5                       6                       7
149 
150 
151 We always think of our offsets as if there were no quirk, and we translate
152 them afterwards, before accessing the memory region.
153 
154 Intended use
155 ------------
156 
157 Drivers that opt to use this API first need to identify which of the above 3
158 quirk combinations (for a total of 8) match what the hardware documentation
159 describes. Then they should wrap the packing() function, creating a new
160 xxx_packing() that calls it using the proper QUIRK_* one-hot bits set.
161 
162 The packing() function returns an int-encoded error code, which protects the
163 programmer against incorrect API use.  The errors are not expected to occur
164 during runtime, therefore it is reasonable for xxx_packing() to return void
165 and simply swallow those errors. Optionally it can dump stack or print the
166 error description.

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php