Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

lib: packing: create __pack() and __unpack() variants without error checking

A future variant of the API, which works on arrays of packed_field
structures, will make most of these checks redundant. The idea will be
that we want to perform sanity checks at compile time, not once
for every function call.

Introduce new variants of pack() and unpack(), which elide the sanity
checks, assuming that the input was pre-sanitized.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Link: https://patch.msgid.link/20241210-packing-pack-fields-and-ice-implementation-v10-1-ee56a47479ac@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Vladimir Oltean and committed by
Jakub Kicinski
c4117091 ae7837bb

+78 -64
+78 -64
lib/packing.c
··· 51 51 return offset_of_group + offset_in_group; 52 52 } 53 53 54 - /** 55 - * pack - Pack u64 number into bitfield of buffer. 56 - * 57 - * @pbuf: Pointer to a buffer holding the packed value. 58 - * @uval: CPU-readable unpacked value to pack. 59 - * @startbit: The index (in logical notation, compensated for quirks) where 60 - * the packed value starts within pbuf. Must be larger than, or 61 - * equal to, endbit. 62 - * @endbit: The index (in logical notation, compensated for quirks) where 63 - * the packed value ends within pbuf. Must be smaller than, or equal 64 - * to, startbit. 65 - * @pbuflen: The length in bytes of the packed buffer pointed to by @pbuf. 66 - * @quirks: A bit mask of QUIRK_LITTLE_ENDIAN, QUIRK_LSW32_IS_FIRST and 67 - * QUIRK_MSB_ON_THE_RIGHT. 68 - * 69 - * Return: 0 on success, EINVAL or ERANGE if called incorrectly. Assuming 70 - * correct usage, return code may be discarded. The @pbuf memory will 71 - * be modified on success. 72 - */ 73 - int pack(void *pbuf, u64 uval, size_t startbit, size_t endbit, size_t pbuflen, 74 - u8 quirks) 54 + static void __pack(void *pbuf, u64 uval, size_t startbit, size_t endbit, 55 + size_t pbuflen, u8 quirks) 75 56 { 76 57 /* Logical byte indices corresponding to the 77 58 * start and end of the field. 78 59 */ 79 - int plogical_first_u8, plogical_last_u8, box; 80 - /* width of the field to access in the pbuf */ 81 - u64 value_width; 82 - 83 - /* startbit is expected to be larger than endbit, and both are 84 - * expected to be within the logically addressable range of the buffer. 85 - */ 86 - if (unlikely(startbit < endbit || startbit >= BITS_PER_BYTE * pbuflen)) 87 - /* Invalid function call */ 88 - return -EINVAL; 89 - 90 - value_width = startbit - endbit + 1; 91 - if (unlikely(value_width > 64)) 92 - return -ERANGE; 93 - 94 - /* Check if "uval" fits in "value_width" bits. 95 - * If value_width is 64, the check will fail, but any 96 - * 64-bit uval will surely fit. 97 - */ 98 - if (unlikely(value_width < 64 && uval >= (1ull << value_width))) 99 - /* Cannot store "uval" inside "value_width" bits. 100 - * Truncating "uval" is most certainly not desirable, 101 - * so simply erroring out is appropriate. 102 - */ 103 - return -ERANGE; 60 + int plogical_first_u8 = startbit / BITS_PER_BYTE; 61 + int plogical_last_u8 = endbit / BITS_PER_BYTE; 62 + int box; 104 63 105 64 /* Iterate through an idealistic view of the pbuf as an u64 with 106 65 * no quirks, u8 by u8 (aligned at u8 boundaries), from high to low 107 66 * logical bit significance. "box" denotes the current logical u8. 108 67 */ 109 - plogical_first_u8 = startbit / BITS_PER_BYTE; 110 - plogical_last_u8 = endbit / BITS_PER_BYTE; 111 - 112 68 for (box = plogical_first_u8; box >= plogical_last_u8; box--) { 113 69 /* Bit indices into the currently accessed 8-bit box */ 114 70 size_t box_start_bit, box_end_bit, box_addr; ··· 119 163 ((u8 *)pbuf)[box_addr] &= ~box_mask; 120 164 ((u8 *)pbuf)[box_addr] |= pval; 121 165 } 122 - return 0; 123 166 } 124 - EXPORT_SYMBOL(pack); 125 167 126 168 /** 127 - * unpack - Unpack u64 number from packed buffer. 169 + * pack - Pack u64 number into bitfield of buffer. 128 170 * 129 171 * @pbuf: Pointer to a buffer holding the packed value. 130 - * @uval: Pointer to an u64 holding the unpacked value. 172 + * @uval: CPU-readable unpacked value to pack. 131 173 * @startbit: The index (in logical notation, compensated for quirks) where 132 174 * the packed value starts within pbuf. Must be larger than, or 133 175 * equal to, endbit. ··· 137 183 * QUIRK_MSB_ON_THE_RIGHT. 138 184 * 139 185 * Return: 0 on success, EINVAL or ERANGE if called incorrectly. Assuming 140 - * correct usage, return code may be discarded. The @uval will be 141 - * modified on success. 186 + * correct usage, return code may be discarded. The @pbuf memory will 187 + * be modified on success. 142 188 */ 143 - int unpack(const void *pbuf, u64 *uval, size_t startbit, size_t endbit, 144 - size_t pbuflen, u8 quirks) 189 + int pack(void *pbuf, u64 uval, size_t startbit, size_t endbit, size_t pbuflen, 190 + u8 quirks) 145 191 { 146 - /* Logical byte indices corresponding to the 147 - * start and end of the field. 148 - */ 149 - int plogical_first_u8, plogical_last_u8, box; 150 192 /* width of the field to access in the pbuf */ 151 193 u64 value_width; 152 194 ··· 157 207 if (unlikely(value_width > 64)) 158 208 return -ERANGE; 159 209 210 + /* Check if "uval" fits in "value_width" bits. 211 + * If value_width is 64, the check will fail, but any 212 + * 64-bit uval will surely fit. 213 + */ 214 + if (value_width < 64 && uval >= (1ull << value_width)) 215 + /* Cannot store "uval" inside "value_width" bits. 216 + * Truncating "uval" is most certainly not desirable, 217 + * so simply erroring out is appropriate. 218 + */ 219 + return -ERANGE; 220 + 221 + __pack(pbuf, uval, startbit, endbit, pbuflen, quirks); 222 + 223 + return 0; 224 + } 225 + EXPORT_SYMBOL(pack); 226 + 227 + static void __unpack(const void *pbuf, u64 *uval, size_t startbit, size_t endbit, 228 + size_t pbuflen, u8 quirks) 229 + { 230 + /* Logical byte indices corresponding to the 231 + * start and end of the field. 232 + */ 233 + int plogical_first_u8 = startbit / BITS_PER_BYTE; 234 + int plogical_last_u8 = endbit / BITS_PER_BYTE; 235 + int box; 236 + 160 237 /* Initialize parameter */ 161 238 *uval = 0; 162 239 ··· 191 214 * no quirks, u8 by u8 (aligned at u8 boundaries), from high to low 192 215 * logical bit significance. "box" denotes the current logical u8. 193 216 */ 194 - plogical_first_u8 = startbit / BITS_PER_BYTE; 195 - plogical_last_u8 = endbit / BITS_PER_BYTE; 196 - 197 217 for (box = plogical_first_u8; box >= plogical_last_u8; box--) { 198 218 /* Bit indices into the currently accessed 8-bit box */ 199 219 size_t box_start_bit, box_end_bit, box_addr; ··· 245 271 *uval &= ~proj_mask; 246 272 *uval |= pval; 247 273 } 274 + } 275 + 276 + /** 277 + * unpack - Unpack u64 number from packed buffer. 278 + * 279 + * @pbuf: Pointer to a buffer holding the packed value. 280 + * @uval: Pointer to an u64 holding the unpacked value. 281 + * @startbit: The index (in logical notation, compensated for quirks) where 282 + * the packed value starts within pbuf. Must be larger than, or 283 + * equal to, endbit. 284 + * @endbit: The index (in logical notation, compensated for quirks) where 285 + * the packed value ends within pbuf. Must be smaller than, or equal 286 + * to, startbit. 287 + * @pbuflen: The length in bytes of the packed buffer pointed to by @pbuf. 288 + * @quirks: A bit mask of QUIRK_LITTLE_ENDIAN, QUIRK_LSW32_IS_FIRST and 289 + * QUIRK_MSB_ON_THE_RIGHT. 290 + * 291 + * Return: 0 on success, EINVAL or ERANGE if called incorrectly. Assuming 292 + * correct usage, return code may be discarded. The @uval will be 293 + * modified on success. 294 + */ 295 + int unpack(const void *pbuf, u64 *uval, size_t startbit, size_t endbit, 296 + size_t pbuflen, u8 quirks) 297 + { 298 + /* width of the field to access in the pbuf */ 299 + u64 value_width; 300 + 301 + /* startbit is expected to be larger than endbit, and both are 302 + * expected to be within the logically addressable range of the buffer. 303 + */ 304 + if (startbit < endbit || startbit >= BITS_PER_BYTE * pbuflen) 305 + /* Invalid function call */ 306 + return -EINVAL; 307 + 308 + value_width = startbit - endbit + 1; 309 + if (value_width > 64) 310 + return -ERANGE; 311 + 312 + __unpack(pbuf, uval, startbit, endbit, pbuflen, quirks); 313 + 248 314 return 0; 249 315 } 250 316 EXPORT_SYMBOL(unpack);