Skip to content

Commit ad1e6fd

Browse files
committed
lib: packing: create __pack() and __unpack() variants without error checking
JIRA: https://issues.redhat.com/browse/RHEL-92666 Upstream commit(s): commit c411709 Author: Vladimir Oltean <vladimir.oltean@nxp.com> Date: Tue Dec 10 12:27:10 2024 -0800 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> Signed-off-by: Petr Oros <poros@redhat.com>
1 parent a650f67 commit ad1e6fd

File tree

1 file changed

+78
-64
lines changed

1 file changed

+78
-64
lines changed

lib/packing.c

Lines changed: 78 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -51,64 +51,20 @@ static size_t calculate_box_addr(size_t box, size_t len, u8 quirks)
5151
return offset_of_group + offset_in_group;
5252
}
5353

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)
7556
{
7657
/* Logical byte indices corresponding to the
7758
* start and end of the field.
7859
*/
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;
10463

10564
/* Iterate through an idealistic view of the pbuf as an u64 with
10665
* no quirks, u8 by u8 (aligned at u8 boundaries), from high to low
10766
* logical bit significance. "box" denotes the current logical u8.
10867
*/
109-
plogical_first_u8 = startbit / BITS_PER_BYTE;
110-
plogical_last_u8 = endbit / BITS_PER_BYTE;
111-
11268
for (box = plogical_first_u8; box >= plogical_last_u8; box--) {
11369
/* Bit indices into the currently accessed 8-bit box */
11470
size_t box_start_bit, box_end_bit, box_addr;
@@ -163,15 +119,13 @@ int pack(void *pbuf, u64 uval, size_t startbit, size_t endbit, size_t pbuflen,
163119
((u8 *)pbuf)[box_addr] &= ~box_mask;
164120
((u8 *)pbuf)[box_addr] |= pval;
165121
}
166-
return 0;
167122
}
168-
EXPORT_SYMBOL(pack);
169123

170124
/**
171-
* unpack - Unpack u64 number from packed buffer.
125+
* pack - Pack u64 number into bitfield of buffer.
172126
*
173127
* @pbuf: Pointer to a buffer holding the packed value.
174-
* @uval: Pointer to an u64 holding the unpacked value.
128+
* @uval: CPU-readable unpacked value to pack.
175129
* @startbit: The index (in logical notation, compensated for quirks) where
176130
* the packed value starts within pbuf. Must be larger than, or
177131
* equal to, endbit.
@@ -183,16 +137,12 @@ EXPORT_SYMBOL(pack);
183137
* QUIRK_MSB_ON_THE_RIGHT.
184138
*
185139
* Return: 0 on success, EINVAL or ERANGE if called incorrectly. Assuming
186-
* correct usage, return code may be discarded. The @uval will be
187-
* modified on success.
140+
* correct usage, return code may be discarded. The @pbuf memory will
141+
* be modified on success.
188142
*/
189-
int unpack(const void *pbuf, u64 *uval, size_t startbit, size_t endbit,
190-
size_t pbuflen, u8 quirks)
143+
int pack(void *pbuf, u64 uval, size_t startbit, size_t endbit, size_t pbuflen,
144+
u8 quirks)
191145
{
192-
/* Logical byte indices corresponding to the
193-
* start and end of the field.
194-
*/
195-
int plogical_first_u8, plogical_last_u8, box;
196146
/* width of the field to access in the pbuf */
197147
u64 value_width;
198148

@@ -207,16 +157,40 @@ int unpack(const void *pbuf, u64 *uval, size_t startbit, size_t endbit,
207157
if (unlikely(value_width > 64))
208158
return -ERANGE;
209159

160+
/* Check if "uval" fits in "value_width" bits.
161+
* If value_width is 64, the check will fail, but any
162+
* 64-bit uval will surely fit.
163+
*/
164+
if (value_width < 64 && uval >= (1ull << value_width))
165+
/* Cannot store "uval" inside "value_width" bits.
166+
* Truncating "uval" is most certainly not desirable,
167+
* so simply erroring out is appropriate.
168+
*/
169+
return -ERANGE;
170+
171+
__pack(pbuf, uval, startbit, endbit, pbuflen, quirks);
172+
173+
return 0;
174+
}
175+
EXPORT_SYMBOL(pack);
176+
177+
static void __unpack(const void *pbuf, u64 *uval, size_t startbit, size_t endbit,
178+
size_t pbuflen, u8 quirks)
179+
{
180+
/* Logical byte indices corresponding to the
181+
* start and end of the field.
182+
*/
183+
int plogical_first_u8 = startbit / BITS_PER_BYTE;
184+
int plogical_last_u8 = endbit / BITS_PER_BYTE;
185+
int box;
186+
210187
/* Initialize parameter */
211188
*uval = 0;
212189

213190
/* Iterate through an idealistic view of the pbuf as an u64 with
214191
* no quirks, u8 by u8 (aligned at u8 boundaries), from high to low
215192
* logical bit significance. "box" denotes the current logical u8.
216193
*/
217-
plogical_first_u8 = startbit / BITS_PER_BYTE;
218-
plogical_last_u8 = endbit / BITS_PER_BYTE;
219-
220194
for (box = plogical_first_u8; box >= plogical_last_u8; box--) {
221195
/* Bit indices into the currently accessed 8-bit box */
222196
size_t box_start_bit, box_end_bit, box_addr;
@@ -271,6 +245,46 @@ int unpack(const void *pbuf, u64 *uval, size_t startbit, size_t endbit,
271245
*uval &= ~proj_mask;
272246
*uval |= pval;
273247
}
248+
}
249+
250+
/**
251+
* unpack - Unpack u64 number from packed buffer.
252+
*
253+
* @pbuf: Pointer to a buffer holding the packed value.
254+
* @uval: Pointer to an u64 holding the unpacked value.
255+
* @startbit: The index (in logical notation, compensated for quirks) where
256+
* the packed value starts within pbuf. Must be larger than, or
257+
* equal to, endbit.
258+
* @endbit: The index (in logical notation, compensated for quirks) where
259+
* the packed value ends within pbuf. Must be smaller than, or equal
260+
* to, startbit.
261+
* @pbuflen: The length in bytes of the packed buffer pointed to by @pbuf.
262+
* @quirks: A bit mask of QUIRK_LITTLE_ENDIAN, QUIRK_LSW32_IS_FIRST and
263+
* QUIRK_MSB_ON_THE_RIGHT.
264+
*
265+
* Return: 0 on success, EINVAL or ERANGE if called incorrectly. Assuming
266+
* correct usage, return code may be discarded. The @uval will be
267+
* modified on success.
268+
*/
269+
int unpack(const void *pbuf, u64 *uval, size_t startbit, size_t endbit,
270+
size_t pbuflen, u8 quirks)
271+
{
272+
/* width of the field to access in the pbuf */
273+
u64 value_width;
274+
275+
/* startbit is expected to be larger than endbit, and both are
276+
* expected to be within the logically addressable range of the buffer.
277+
*/
278+
if (startbit < endbit || startbit >= BITS_PER_BYTE * pbuflen)
279+
/* Invalid function call */
280+
return -EINVAL;
281+
282+
value_width = startbit - endbit + 1;
283+
if (value_width > 64)
284+
return -ERANGE;
285+
286+
__unpack(pbuf, uval, startbit, endbit, pbuflen, quirks);
287+
274288
return 0;
275289
}
276290
EXPORT_SYMBOL(unpack);

0 commit comments

Comments
 (0)