mirror of
https://github.com/torvalds/linux.git
synced 2026-10-22 23:01:49 +02:00
bitmap updates for v7.4
- __MAKE_OP() removal (Yury, Mark); - bitmap parsing fixes (Shashank); - Rust docs updates (Georgios). -----BEGIN PGP SIGNATURE----- iQGzBAABCgAdFiEEi8GdvG6xMhdgpu/4sUSA/TofvsgFAmrVbSMACgkQsUSA/Tof vshlsQv+NeRJp2focN/6QYq9ec2tp8uwdY1Ur9tiHdonE3Oq04EMNjbsVOLxn9u2 eFfTzb7UyjCjKGab8h0ZzZxg34rBCvIYCwW66FcEeXzpPiTJVKPHYx6Mp+Gg1UiF QSIRXJsXiI5zj7ltORBb+FYHVVwGN80EGle1fjAN3cTA5OmiVcwLVml8jCfTzUJJ lEsJm57MDyH3XVnrBTm4HE8yMQZkDYhh8KUFQClZJsl7D9VcymtNIqkz33lm1Zqh ItoYq4nJD0t4emTVRvH+KcfJnnv1my68rErbDNv7T0gjKY/razPkN+EFeB6e6NFv J6lFW2OHTeAmpbMSxUCHuqx5m/wRxPdlkN1o3CoAd+pUbjs/Dz59PnffTlGLw6yD AMg3m+6/4B+Ucmb6+WWpEHEuixUXm1Vnjl63EHaHPJNHFRzQGKnEtMJblKphwE7k v0sq75ev4rvZ6SACICydZa0l88M8Z/q3Rj0W6SmuQHRZObsHLPprzqn5KIeEfTjO 7iv6Vkry =5Jv7 -----END PGP SIGNATURE----- Merge tag 'bitmap-for-v7.4-rc1' of https://github.com/norov/linux Pull bitmap updates from Yury Norov: "This includes __MAKE_OP() macro removal from me with the follow-up from Mark, cleanups for bitmaps parser from Shashank and a couple Rust docs fixes from Georgios" * tag 'bitmap-for-v7.4-rc1' of https://github.com/norov/linux: rust: bitmap: document panics in `next_bit` and `next_zero_bit` rust: id_pool: document panics in `find_unused_id` and `release_id` bitmap: test bitmap_parselist() with a group size close to UINT_MAX bitmap: bitmap_parselist(): don't wrap around on a huge group size bitmap: test bitmap_parselist() with text after the group size bitmap: bitmap_parselist(): reject trailing characters after group size bitmap: test bitmap_parse() with an illegal character before 8 hex digits bitmap: bitmap_parse(): reject non-hex character before 8 digits bitfield: Restore be16_replace_bits() bitfield: get rid of __MAKE_OP machinery
This commit is contained in:
commit
9ba46df344
|
|
@ -4636,6 +4636,7 @@ BITMAP API
|
|||
M: Yury Norov <yury.norov@gmail.com>
|
||||
R: Rasmus Villemoes <linux@rasmusvillemoes.dk>
|
||||
S: Maintained
|
||||
F: include/linux/bitfield-fix-width.h
|
||||
F: include/linux/bitfield.h
|
||||
F: include/linux/bitmap-str.h
|
||||
F: include/linux/bitmap.h
|
||||
|
|
@ -4656,6 +4657,7 @@ F: lib/find_bit_benchmark.c
|
|||
F: lib/region_alloc_benchmark.c
|
||||
F: lib/test_bitmap.c
|
||||
F: lib/tests/cpumask_kunit.c
|
||||
F: tools/include/linux/bitfield-fix-width.h
|
||||
F: tools/include/linux/bitfield.h
|
||||
F: tools/include/linux/bitmap.h
|
||||
F: tools/include/linux/bits.h
|
||||
|
|
|
|||
241
include/linux/bitfield-fix-width.h
Normal file
241
include/linux/bitfield-fix-width.h
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#ifndef _LINUX_BITFIELD_FIX_WIDTH_H
|
||||
#define _LINUX_BITFIELD_FIX_WIDTH_H
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/types.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
extern void __compiletime_error("value doesn't fit into mask")
|
||||
__field_overflow(void);
|
||||
|
||||
extern void __compiletime_error("bad bitfield mask")
|
||||
__bad_mask(void);
|
||||
|
||||
static __always_inline
|
||||
u64 field_multiplier(u64 field)
|
||||
{
|
||||
if ((field | (field - 1)) & ((field | (field - 1)) + 1))
|
||||
__bad_mask();
|
||||
return field & -field;
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
u64 field_mask(u64 field)
|
||||
{
|
||||
return field / field_multiplier(field);
|
||||
}
|
||||
|
||||
#define field_max(field) ((typeof(field))field_mask(field))
|
||||
|
||||
#define __assert_field(v, field) \
|
||||
do { \
|
||||
if (__builtin_constant_p(v) && \
|
||||
((v) & ~field_mask(field))) \
|
||||
__field_overflow(); \
|
||||
} while (0)
|
||||
|
||||
static __always_inline __must_check
|
||||
__u8 u8_encode_bits(u8 v, u8 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return (v & field_mask(field)) * field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
__u8 u8_replace_bits(__u8 old, u8 val, u8 field)
|
||||
{
|
||||
return (old & ~field) | u8_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
void u8p_replace_bits(__u8 *p, u8 val, u8 field)
|
||||
{
|
||||
*p = (*p & ~field) | u8_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
u8 u8_get_bits(__u8 v, u8 field)
|
||||
{
|
||||
return (v & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
__le16 le16_encode_bits(u16 v, u16 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return cpu_to_le16((v & field_mask(field)) * field_multiplier(field));
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
void le16p_replace_bits(__le16 *p, u16 val, u16 field)
|
||||
{
|
||||
*p = (*p & ~cpu_to_le16(field)) | le16_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
u16 le16_get_bits(__le16 v, u16 field)
|
||||
{
|
||||
return (le16_to_cpu(v) & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
__be16 be16_encode_bits(u16 v, u16 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return cpu_to_be16((v & field_mask(field)) * field_multiplier(field));
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
u16 be16_get_bits(__be16 v, u16 field)
|
||||
{
|
||||
return (be16_to_cpu(v) & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
__be16 be16_replace_bits(__be16 old, u16 val, u16 field)
|
||||
{
|
||||
return (old & ~cpu_to_be16(field)) | be16_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
__u16 u16_encode_bits(u16 v, u16 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return (v & field_mask(field)) * field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
__u16 u16_replace_bits(__u16 old, u16 val, u16 field)
|
||||
{
|
||||
return (old & ~field) | u16_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
void u16p_replace_bits(__u16 *p, u16 val, u16 field)
|
||||
{
|
||||
*p = (*p & ~field) | u16_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
u16 u16_get_bits(__u16 v, u16 field)
|
||||
{
|
||||
return (v & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
__le32 le32_encode_bits(u32 v, u32 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return cpu_to_le32((v & field_mask(field)) * field_multiplier(field));
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
void le32p_replace_bits(__le32 *p, u32 val, u32 field)
|
||||
{
|
||||
*p = (*p & ~cpu_to_le32(field)) | le32_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
u32 le32_get_bits(__le32 v, u32 field)
|
||||
{
|
||||
return (le32_to_cpu(v) & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
__be32 be32_encode_bits(u32 v, u32 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return cpu_to_be32((v & field_mask(field)) * field_multiplier(field));
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
void be32p_replace_bits(__be32 *p, u32 val, u32 field)
|
||||
{
|
||||
*p = (*p & ~cpu_to_be32(field)) | be32_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
u32 be32_get_bits(__be32 v, u32 field)
|
||||
{
|
||||
return (be32_to_cpu(v) & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
__u32 u32_encode_bits(u32 v, u32 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return (v & field_mask(field)) * field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
__u32 u32_replace_bits(__u32 old, u32 val, u32 field)
|
||||
{
|
||||
return (old & ~field) | u32_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
void u32p_replace_bits(__u32 *p, u32 val, u32 field)
|
||||
{
|
||||
*p = (*p & ~field) | u32_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
u32 u32_get_bits(__u32 v, u32 field)
|
||||
{
|
||||
return (v & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
__le64 le64_encode_bits(u64 v, u64 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return cpu_to_le64((v & field_mask(field)) * field_multiplier(field));
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
u64 le64_get_bits(__le64 v, u64 field)
|
||||
{
|
||||
return (le64_to_cpu(v) & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
__be64 be64_encode_bits(u64 v, u64 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return cpu_to_be64((v & field_mask(field)) * field_multiplier(field));
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
u64 be64_get_bits(__be64 v, u64 field)
|
||||
{
|
||||
return (be64_to_cpu(v) & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
__u64 u64_encode_bits(u64 v, u64 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return (v & field_mask(field)) * field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
__u64 u64_replace_bits(__u64 old, u64 val, u64 field)
|
||||
{
|
||||
return (old & ~field) | u64_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
void u64p_replace_bits(__u64 *p, u64 val, u64 field)
|
||||
{
|
||||
*p = (*p & ~field) | u64_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
u64 u64_get_bits(__u64 v, u64 field)
|
||||
{
|
||||
return (v & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
#endif /* _LINUX_BITFIELD_FIX_WIDTH_H */
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
#include <linux/build_bug.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/typecheck.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/bitfield-fix-width.h>
|
||||
|
||||
/*
|
||||
* Bitfield access macros
|
||||
|
|
@ -211,53 +211,6 @@
|
|||
*(_reg_p) |= (((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask)); \
|
||||
})
|
||||
|
||||
extern void __compiletime_error("value doesn't fit into mask")
|
||||
__field_overflow(void);
|
||||
extern void __compiletime_error("bad bitfield mask")
|
||||
__bad_mask(void);
|
||||
static __always_inline u64 field_multiplier(u64 field)
|
||||
{
|
||||
if ((field | (field - 1)) & ((field | (field - 1)) + 1))
|
||||
__bad_mask();
|
||||
return field & -field;
|
||||
}
|
||||
static __always_inline u64 field_mask(u64 field)
|
||||
{
|
||||
return field / field_multiplier(field);
|
||||
}
|
||||
#define field_max(field) ((typeof(field))field_mask(field))
|
||||
#define ____MAKE_OP(type,base,to,from) \
|
||||
static __always_inline __##type __must_check type##_encode_bits(base v, base field) \
|
||||
{ \
|
||||
if (__builtin_constant_p(v) && (v & ~field_mask(field))) \
|
||||
__field_overflow(); \
|
||||
return to((v & field_mask(field)) * field_multiplier(field)); \
|
||||
} \
|
||||
static __always_inline __##type __must_check type##_replace_bits(__##type old, \
|
||||
base val, base field) \
|
||||
{ \
|
||||
return (old & ~to(field)) | type##_encode_bits(val, field); \
|
||||
} \
|
||||
static __always_inline void type##p_replace_bits(__##type *p, \
|
||||
base val, base field) \
|
||||
{ \
|
||||
*p = (*p & ~to(field)) | type##_encode_bits(val, field); \
|
||||
} \
|
||||
static __always_inline base __must_check type##_get_bits(__##type v, base field) \
|
||||
{ \
|
||||
return (from(v) & field)/field_multiplier(field); \
|
||||
}
|
||||
#define __MAKE_OP(size) \
|
||||
____MAKE_OP(le##size,u##size,cpu_to_le##size,le##size##_to_cpu) \
|
||||
____MAKE_OP(be##size,u##size,cpu_to_be##size,be##size##_to_cpu) \
|
||||
____MAKE_OP(u##size,u##size,,)
|
||||
____MAKE_OP(u8,u8,,)
|
||||
__MAKE_OP(16)
|
||||
__MAKE_OP(32)
|
||||
__MAKE_OP(64)
|
||||
#undef __MAKE_OP
|
||||
#undef ____MAKE_OP
|
||||
|
||||
#define __field_prep(mask, val) \
|
||||
({ \
|
||||
auto __mask = (mask); \
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include <linux/hex.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/overflow.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include "kstrtox.h"
|
||||
|
|
@ -186,10 +187,12 @@ struct region {
|
|||
|
||||
static void bitmap_set_region(const struct region *r, unsigned long *bitmap)
|
||||
{
|
||||
unsigned int start;
|
||||
unsigned int start = r->start;
|
||||
|
||||
for (start = r->start; start <= r->end; start += r->group_len)
|
||||
do {
|
||||
bitmap_set(bitmap, start, min(r->end - start + 1, r->off));
|
||||
} while (!check_add_overflow(start, r->group_len, &start) &&
|
||||
start <= r->end);
|
||||
}
|
||||
|
||||
static int bitmap_check_region(const struct region *r)
|
||||
|
|
@ -299,7 +302,14 @@ static const char *bitmap_parse_region(const char *str, struct region *r)
|
|||
if (*str != '/')
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
return bitmap_getnum(str + 1, &r->group_len, lastbit);
|
||||
str = bitmap_getnum(str + 1, &r->group_len, lastbit);
|
||||
if (IS_ERR(str))
|
||||
return str;
|
||||
|
||||
if (!end_of_region(*str))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
return end_of_str(*str) ? NULL : str;
|
||||
|
||||
no_end:
|
||||
r->end = r->start;
|
||||
|
|
@ -414,8 +424,12 @@ static const char *bitmap_get_x32_reverse(const char *start,
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (hex_to_bin(*end--) >= 0)
|
||||
return ERR_PTR(-EOVERFLOW);
|
||||
/*
|
||||
* Eight digits have been consumed and the next character is not a
|
||||
* separator: another hex digit means the chunk does not fit in 32
|
||||
* bits, anything else is an illegal character.
|
||||
*/
|
||||
return ERR_PTR(hex_to_bin(*end) >= 0 ? -EOVERFLOW : -EINVAL);
|
||||
out:
|
||||
*num = ret;
|
||||
return end;
|
||||
|
|
|
|||
|
|
@ -502,6 +502,8 @@ static const struct test_bitmap_parselist parselist_tests[] __initconst = {
|
|||
{0, "0-N:1/3,1-N:1/3,2-N:1/3", &exp1[8 * step], 32, 0},
|
||||
{0, "0-31:1/3,1-31:1/3,2-31:1/3", &exp1[8 * step], 32, 0},
|
||||
{0, "1-10:8/12,8-31:24/29,0-31:0/3", &exp1[9 * step], 32, 0},
|
||||
{0, "1-1:1/4294967295", &exp1[1 * step], 32, 0},
|
||||
{0, "15-15:1/4294967281", &exp1[13 * step], 32, 0},
|
||||
|
||||
{0, "all", &exp1[8 * step], 32, 0},
|
||||
{0, "0, 1, all, ", &exp1[8 * step], 32, 0},
|
||||
|
|
@ -528,6 +530,9 @@ static const struct test_bitmap_parselist parselist_tests[] __initconst = {
|
|||
{-EINVAL, "a-31:10/1", NULL, 8, 0},
|
||||
{-EINVAL, "0-31:a/1", NULL, 8, 0},
|
||||
{-EINVAL, "0-\n", NULL, 8, 0},
|
||||
{-EINVAL, "0-7:1/2N", NULL, 8, 0},
|
||||
{-EINVAL, "0-7:1/2all", NULL, 8, 0},
|
||||
{-EINVAL, "all:1/2N", NULL, 8, 0},
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -643,6 +648,10 @@ static const struct test_bitmap_parselist parse_tests[] __initconst = {
|
|||
{-EOVERFLOW, "badf00d,deadbeef,1,0", NULL, 90, 0},
|
||||
{-EOVERFLOW, "fbadf00d,deadbeef,1,0", NULL, 95, 0},
|
||||
{-EOVERFLOW, "badf00d,deadbeef,1,0", NULL, 100, 0},
|
||||
|
||||
{-EINVAL, "x12345678", NULL, 32, 0},
|
||||
{-EINVAL, "1g12345678", NULL, 64, 0},
|
||||
{-EINVAL, "0x0000000f", NULL, 64, 0},
|
||||
#undef step
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -459,7 +459,13 @@ pub fn last_bit(&self) -> Option<usize> {
|
|||
|
||||
/// Finds next set bit, starting from `start`.
|
||||
///
|
||||
/// Returns `None` if `start` is greater or equal to `self.nbits`.
|
||||
/// Returns `None` if no bits are set on or after the given index. The
|
||||
/// index `start` must be in bounds.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `CONFIG_RUST_BITMAP_HARDENED` is enabled and `start` is
|
||||
/// out of bounds.
|
||||
#[inline]
|
||||
pub fn next_bit(&self, start: usize) -> Option<usize> {
|
||||
bitmap_assert!(
|
||||
|
|
@ -479,7 +485,14 @@ pub fn next_bit(&self, start: usize) -> Option<usize> {
|
|||
}
|
||||
|
||||
/// Finds next zero bit, starting from `start`.
|
||||
/// Returns `None` if `start` is greater than or equal to `self.len()`.
|
||||
///
|
||||
/// Returns `None` if no bits are zero on or after the given index. The
|
||||
/// index `start` must be in bounds.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `CONFIG_RUST_BITMAP_HARDENED` is enabled and `start` is
|
||||
/// out of bounds.
|
||||
#[inline]
|
||||
pub fn next_zero_bit(&self, start: usize) -> Option<usize> {
|
||||
bitmap_assert!(
|
||||
|
|
|
|||
|
|
@ -224,7 +224,13 @@ pub fn grow(&mut self, mut resizer: PoolResizer) {
|
|||
/// Finds an unused ID in the bitmap.
|
||||
///
|
||||
/// Upon success, returns its index. Otherwise, returns [`None`]
|
||||
/// to indicate that a [`Self::grow_request`] is needed.
|
||||
/// to indicate that a [`Self::grow_request`] is needed. `offset` must be
|
||||
/// within bounds.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `CONFIG_RUST_BITMAP_HARDENED` is enabled and `offset` is out
|
||||
/// of bounds.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn find_unused_id(&mut self, offset: usize) -> Option<UnusedId<'_>> {
|
||||
|
|
@ -236,6 +242,13 @@ pub fn find_unused_id(&mut self, offset: usize) -> Option<UnusedId<'_>> {
|
|||
}
|
||||
|
||||
/// Releases an ID.
|
||||
///
|
||||
/// The `id` must be within bounds.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `CONFIG_RUST_BITMAP_HARDENED` is enabled and `id` is out of
|
||||
/// bounds.
|
||||
#[inline]
|
||||
pub fn release_id(&mut self, id: usize) {
|
||||
self.map.clear_bit(id);
|
||||
|
|
|
|||
236
tools/include/linux/bitfield-fix-width.h
Normal file
236
tools/include/linux/bitfield-fix-width.h
Normal file
|
|
@ -0,0 +1,236 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#ifndef _LINUX_BITFIELD_FIX_WIDTH_H
|
||||
#define _LINUX_BITFIELD_FIX_WIDTH_H
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
extern void __compiletime_error("value doesn't fit into mask")
|
||||
__field_overflow(void);
|
||||
|
||||
extern void __compiletime_error("bad bitfield mask")
|
||||
__bad_mask(void);
|
||||
|
||||
static __always_inline
|
||||
u64 field_multiplier(u64 field)
|
||||
{
|
||||
if ((field | (field - 1)) & ((field | (field - 1)) + 1))
|
||||
__bad_mask();
|
||||
return field & -field;
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
u64 field_mask(u64 field)
|
||||
{
|
||||
return field / field_multiplier(field);
|
||||
}
|
||||
|
||||
#define field_max(field) ((typeof(field))field_mask(field))
|
||||
|
||||
#define __assert_field(v, field) \
|
||||
do { \
|
||||
if (__builtin_constant_p(v) && \
|
||||
((v) & ~field_mask(field))) \
|
||||
__field_overflow(); \
|
||||
} while (0)
|
||||
|
||||
static __always_inline
|
||||
__u8 u8_encode_bits(u8 v, u8 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return (v & field_mask(field)) * field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
__u8 u8_replace_bits(__u8 old, u8 val, u8 field)
|
||||
{
|
||||
return (old & ~field) | u8_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
void u8p_replace_bits(__u8 *p, u8 val, u8 field)
|
||||
{
|
||||
*p = (*p & ~field) | u8_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
u8 u8_get_bits(__u8 v, u8 field)
|
||||
{
|
||||
return (v & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
__le16 le16_encode_bits(u16 v, u16 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return cpu_to_le16((v & field_mask(field)) * field_multiplier(field));
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
void le16p_replace_bits(__le16 *p, u16 val, u16 field)
|
||||
{
|
||||
*p = (*p & ~cpu_to_le16(field)) | le16_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
u16 le16_get_bits(__le16 v, u16 field)
|
||||
{
|
||||
return (le16_to_cpu(v) & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
__be16 be16_encode_bits(u16 v, u16 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return cpu_to_be16((v & field_mask(field)) * field_multiplier(field));
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
u16 be16_get_bits(__be16 v, u16 field)
|
||||
{
|
||||
return (be16_to_cpu(v) & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
__u16 u16_encode_bits(u16 v, u16 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return (v & field_mask(field)) * field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
__u16 u16_replace_bits(__u16 old, u16 val, u16 field)
|
||||
{
|
||||
return (old & ~field) | u16_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
void u16p_replace_bits(__u16 *p, u16 val, u16 field)
|
||||
{
|
||||
*p = (*p & ~field) | u16_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
u16 u16_get_bits(__u16 v, u16 field)
|
||||
{
|
||||
return (v & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
__le32 le32_encode_bits(u32 v, u32 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return cpu_to_le32((v & field_mask(field)) * field_multiplier(field));
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
void le32p_replace_bits(__le32 *p, u32 val, u32 field)
|
||||
{
|
||||
*p = (*p & ~cpu_to_le32(field)) | le32_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
u32 le32_get_bits(__le32 v, u32 field)
|
||||
{
|
||||
return (le32_to_cpu(v) & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
__be32 be32_encode_bits(u32 v, u32 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return cpu_to_be32((v & field_mask(field)) * field_multiplier(field));
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
void be32p_replace_bits(__be32 *p, u32 val, u32 field)
|
||||
{
|
||||
*p = (*p & ~cpu_to_be32(field)) | be32_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
u32 be32_get_bits(__be32 v, u32 field)
|
||||
{
|
||||
return (be32_to_cpu(v) & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
__u32 u32_encode_bits(u32 v, u32 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return (v & field_mask(field)) * field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
__u32 u32_replace_bits(__u32 old, u32 val, u32 field)
|
||||
{
|
||||
return (old & ~field) | u32_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
void u32p_replace_bits(__u32 *p, u32 val, u32 field)
|
||||
{
|
||||
*p = (*p & ~field) | u32_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
u32 u32_get_bits(__u32 v, u32 field)
|
||||
{
|
||||
return (v & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
__le64 le64_encode_bits(u64 v, u64 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return cpu_to_le64((v & field_mask(field)) * field_multiplier(field));
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
u64 le64_get_bits(__le64 v, u64 field)
|
||||
{
|
||||
return (le64_to_cpu(v) & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
__be64 be64_encode_bits(u64 v, u64 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return cpu_to_be64((v & field_mask(field)) * field_multiplier(field));
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
u64 be64_get_bits(__be64 v, u64 field)
|
||||
{
|
||||
return (be64_to_cpu(v) & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
__u64 u64_encode_bits(u64 v, u64 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return (v & field_mask(field)) * field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
__u64 u64_replace_bits(__u64 old, u64 val, u64 field)
|
||||
{
|
||||
return (old & ~field) | u64_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
void u64p_replace_bits(__u64 *p, u64 val, u64 field)
|
||||
{
|
||||
*p = (*p & ~field) | u64_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
u64 u64_get_bits(__u64 v, u64 field)
|
||||
{
|
||||
return (v & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
#endif /* _LINUX_BITFIELD_FIX_WIDTH_H */
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
#include <linux/build_bug.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/bitfield-fix-width.h>
|
||||
|
||||
/*
|
||||
* Bitfield access macros
|
||||
|
|
@ -127,51 +127,4 @@
|
|||
(typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); \
|
||||
})
|
||||
|
||||
extern void __compiletime_error("value doesn't fit into mask")
|
||||
__field_overflow(void);
|
||||
extern void __compiletime_error("bad bitfield mask")
|
||||
__bad_mask(void);
|
||||
static __always_inline u64 field_multiplier(u64 field)
|
||||
{
|
||||
if ((field | (field - 1)) & ((field | (field - 1)) + 1))
|
||||
__bad_mask();
|
||||
return field & -field;
|
||||
}
|
||||
static __always_inline u64 field_mask(u64 field)
|
||||
{
|
||||
return field / field_multiplier(field);
|
||||
}
|
||||
#define field_max(field) ((typeof(field))field_mask(field))
|
||||
#define ____MAKE_OP(type,base,to,from) \
|
||||
static __always_inline __##type type##_encode_bits(base v, base field) \
|
||||
{ \
|
||||
if (__builtin_constant_p(v) && (v & ~field_mask(field))) \
|
||||
__field_overflow(); \
|
||||
return to((v & field_mask(field)) * field_multiplier(field)); \
|
||||
} \
|
||||
static __always_inline __##type type##_replace_bits(__##type old, \
|
||||
base val, base field) \
|
||||
{ \
|
||||
return (old & ~to(field)) | type##_encode_bits(val, field); \
|
||||
} \
|
||||
static __always_inline void type##p_replace_bits(__##type *p, \
|
||||
base val, base field) \
|
||||
{ \
|
||||
*p = (*p & ~to(field)) | type##_encode_bits(val, field); \
|
||||
} \
|
||||
static __always_inline base type##_get_bits(__##type v, base field) \
|
||||
{ \
|
||||
return (from(v) & field)/field_multiplier(field); \
|
||||
}
|
||||
#define __MAKE_OP(size) \
|
||||
____MAKE_OP(le##size,u##size,cpu_to_le##size,le##size##_to_cpu) \
|
||||
____MAKE_OP(be##size,u##size,cpu_to_be##size,be##size##_to_cpu) \
|
||||
____MAKE_OP(u##size,u##size,,)
|
||||
____MAKE_OP(u8,u8,,)
|
||||
__MAKE_OP(16)
|
||||
__MAKE_OP(32)
|
||||
__MAKE_OP(64)
|
||||
#undef __MAKE_OP
|
||||
#undef ____MAKE_OP
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user