Skip to content

Commit 8b2198f

Browse files
committed
Merge tag 'bitmap-for-6.16-rc1' of https://github.com/norov/linux
Pull bitmap updates from Yury Norov: - dead code cleanups for cpumasks and nodemasks (me) - fixed-width flavors of GENMASK() and BIT() (Vincent, Lucas and me) - FIELD_MODIFY() helper (Luo) - for_each_node_with_cpus() optimization (me) - bitmap-str fixes (Andy) * tag 'bitmap-for-6.16-rc1' of https://github.com/norov/linux: topology: make for_each_node_with_cpus() O(N) bitfield: Add FIELD_MODIFY() helper bitmap-str: Add missing header(s) bitmap-str: Get rid of 'extern' for function prototypes build_bug.h: more user friendly error messages in BUILD_BUG_ON_ZERO() test_bits: add tests for BIT_U*() test_bits: add tests for GENMASK_U*() drm/i915: Convert REG_GENMASK*() to fixed-width GENMASK_U*() bits: introduce fixed-type BIT_U*() bits: introduce fixed-type GENMASK_U*() bits: add comments and newlines to #if, #else and #endif directives cpumask: drop cpumask_assign_cpu() riscv: switch set_icache_stale_mask() to using non-atomic assign_cpu() cpumask: add non-atomic __assign_cpu() nodemask: drop nodes_shift
2 parents 546b1c9 + 895ee6a commit 8b2198f

File tree

12 files changed

+134
-153
lines changed

12 files changed

+134
-153
lines changed

arch/riscv/mm/cacheflush.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ static void set_icache_stale_mask(void)
172172
stale_cpu = cpumask_test_cpu(cpu, mask);
173173

174174
cpumask_setall(mask);
175-
cpumask_assign_cpu(cpu, mask, stale_cpu);
175+
__assign_cpu(cpu, mask, stale_cpu);
176176
put_cpu();
177177
}
178178
#endif

drivers/gpu/drm/i915/i915_reg_defs.h

Lines changed: 11 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -9,76 +9,19 @@
99
#include <linux/bitfield.h>
1010
#include <linux/bits.h>
1111

12-
/**
13-
* REG_BIT() - Prepare a u32 bit value
14-
* @__n: 0-based bit number
15-
*
16-
* Local wrapper for BIT() to force u32, with compile time checks.
17-
*
18-
* @return: Value with bit @__n set.
19-
*/
20-
#define REG_BIT(__n) \
21-
((u32)(BIT(__n) + \
22-
BUILD_BUG_ON_ZERO(__is_constexpr(__n) && \
23-
((__n) < 0 || (__n) > 31))))
24-
25-
/**
26-
* REG_BIT8() - Prepare a u8 bit value
27-
* @__n: 0-based bit number
28-
*
29-
* Local wrapper for BIT() to force u8, with compile time checks.
30-
*
31-
* @return: Value with bit @__n set.
32-
*/
33-
#define REG_BIT8(__n) \
34-
((u8)(BIT(__n) + \
35-
BUILD_BUG_ON_ZERO(__is_constexpr(__n) && \
36-
((__n) < 0 || (__n) > 7))))
37-
38-
/**
39-
* REG_GENMASK() - Prepare a continuous u32 bitmask
40-
* @__high: 0-based high bit
41-
* @__low: 0-based low bit
42-
*
43-
* Local wrapper for GENMASK() to force u32, with compile time checks.
44-
*
45-
* @return: Continuous bitmask from @__high to @__low, inclusive.
46-
*/
47-
#define REG_GENMASK(__high, __low) \
48-
((u32)(GENMASK(__high, __low) + \
49-
BUILD_BUG_ON_ZERO(__is_constexpr(__high) && \
50-
__is_constexpr(__low) && \
51-
((__low) < 0 || (__high) > 31 || (__low) > (__high)))))
52-
53-
/**
54-
* REG_GENMASK64() - Prepare a continuous u64 bitmask
55-
* @__high: 0-based high bit
56-
* @__low: 0-based low bit
57-
*
58-
* Local wrapper for GENMASK_ULL() to force u64, with compile time checks.
59-
*
60-
* @return: Continuous bitmask from @__high to @__low, inclusive.
12+
/*
13+
* Wrappers over the generic fixed width BIT_U*() and GENMASK_U*()
14+
* implementations, for compatibility reasons with previous implementation.
6115
*/
62-
#define REG_GENMASK64(__high, __low) \
63-
((u64)(GENMASK_ULL(__high, __low) + \
64-
BUILD_BUG_ON_ZERO(__is_constexpr(__high) && \
65-
__is_constexpr(__low) && \
66-
((__low) < 0 || (__high) > 63 || (__low) > (__high)))))
16+
#define REG_GENMASK(high, low) GENMASK_U32(high, low)
17+
#define REG_GENMASK64(high, low) GENMASK_U64(high, low)
18+
#define REG_GENMASK16(high, low) GENMASK_U16(high, low)
19+
#define REG_GENMASK8(high, low) GENMASK_U8(high, low)
6720

68-
/**
69-
* REG_GENMASK8() - Prepare a continuous u8 bitmask
70-
* @__high: 0-based high bit
71-
* @__low: 0-based low bit
72-
*
73-
* Local wrapper for GENMASK() to force u8, with compile time checks.
74-
*
75-
* @return: Continuous bitmask from @__high to @__low, inclusive.
76-
*/
77-
#define REG_GENMASK8(__high, __low) \
78-
((u8)(GENMASK(__high, __low) + \
79-
BUILD_BUG_ON_ZERO(__is_constexpr(__high) && \
80-
__is_constexpr(__low) && \
81-
((__low) < 0 || (__high) > 7 || (__low) > (__high)))))
21+
#define REG_BIT(n) BIT_U32(n)
22+
#define REG_BIT64(n) BIT_U64(n)
23+
#define REG_BIT16(n) BIT_U16(n)
24+
#define REG_BIT8(n) BIT_U8(n)
8225

8326
/*
8427
* Local integer constant expression version of is_power_of_2().
@@ -143,35 +86,6 @@
14386
*/
14487
#define REG_FIELD_GET64(__mask, __val) ((u64)FIELD_GET(__mask, __val))
14588

146-
/**
147-
* REG_BIT16() - Prepare a u16 bit value
148-
* @__n: 0-based bit number
149-
*
150-
* Local wrapper for BIT() to force u16, with compile time
151-
* checks.
152-
*
153-
* @return: Value with bit @__n set.
154-
*/
155-
#define REG_BIT16(__n) \
156-
((u16)(BIT(__n) + \
157-
BUILD_BUG_ON_ZERO(__is_constexpr(__n) && \
158-
((__n) < 0 || (__n) > 15))))
159-
160-
/**
161-
* REG_GENMASK16() - Prepare a continuous u8 bitmask
162-
* @__high: 0-based high bit
163-
* @__low: 0-based low bit
164-
*
165-
* Local wrapper for GENMASK() to force u16, with compile time
166-
* checks.
167-
*
168-
* @return: Continuous bitmask from @__high to @__low, inclusive.
169-
*/
170-
#define REG_GENMASK16(__high, __low) \
171-
((u16)(GENMASK(__high, __low) + \
172-
BUILD_BUG_ON_ZERO(__is_constexpr(__high) && \
173-
__is_constexpr(__low) && \
174-
((__low) < 0 || (__high) > 15 || (__low) > (__high)))))
17589

17690
/**
17791
* REG_FIELD_PREP16() - Prepare a u16 bitfield value

include/linux/bitfield.h

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#define _LINUX_BITFIELD_H
99

1010
#include <linux/build_bug.h>
11+
#include <linux/typecheck.h>
1112
#include <asm/byteorder.h>
1213

1314
/*
@@ -38,8 +39,7 @@
3839
* FIELD_PREP(REG_FIELD_D, 0x40);
3940
*
4041
* Modify:
41-
* reg &= ~REG_FIELD_C;
42-
* reg |= FIELD_PREP(REG_FIELD_C, c);
42+
* FIELD_MODIFY(REG_FIELD_C, &reg, c);
4343
*/
4444

4545
#define __bf_shf(x) (__builtin_ffsll(x) - 1)
@@ -156,6 +156,23 @@
156156
(typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); \
157157
})
158158

159+
/**
160+
* FIELD_MODIFY() - modify a bitfield element
161+
* @_mask: shifted mask defining the field's length and position
162+
* @_reg_p: pointer to the memory that should be updated
163+
* @_val: value to store in the bitfield
164+
*
165+
* FIELD_MODIFY() modifies the set of bits in @_reg_p specified by @_mask,
166+
* by replacing them with the bitfield value passed in as @_val.
167+
*/
168+
#define FIELD_MODIFY(_mask, _reg_p, _val) \
169+
({ \
170+
typecheck_pointer(_reg_p); \
171+
__BF_FIELD_CHECK(_mask, *(_reg_p), _val, "FIELD_MODIFY: "); \
172+
*(_reg_p) &= ~(_mask); \
173+
*(_reg_p) |= (((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask)); \
174+
})
175+
159176
extern void __compiletime_error("value doesn't fit into mask")
160177
__field_overflow(void);
161178
extern void __compiletime_error("bad bitfield mask")

include/linux/bitmap-str.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22
#ifndef __LINUX_BITMAP_STR_H
33
#define __LINUX_BITMAP_STR_H
44

5+
#include <linux/types.h>
6+
57
int bitmap_parse_user(const char __user *ubuf, unsigned int ulen, unsigned long *dst, int nbits);
68
int bitmap_print_to_pagebuf(bool list, char *buf, const unsigned long *maskp, int nmaskbits);
7-
extern int bitmap_print_bitmask_to_buf(char *buf, const unsigned long *maskp,
8-
int nmaskbits, loff_t off, size_t count);
9-
extern int bitmap_print_list_to_buf(char *buf, const unsigned long *maskp,
10-
int nmaskbits, loff_t off, size_t count);
9+
int bitmap_print_bitmask_to_buf(char *buf, const unsigned long *maskp, int nmaskbits,
10+
loff_t off, size_t count);
11+
int bitmap_print_list_to_buf(char *buf, const unsigned long *maskp, int nmaskbits,
12+
loff_t off, size_t count);
1113
int bitmap_parse(const char *buf, unsigned int buflen, unsigned long *dst, int nbits);
1214
int bitmap_parselist(const char *buf, unsigned long *maskp, int nmaskbits);
1315
int bitmap_parselist_user(const char __user *ubuf, unsigned int ulen,

include/linux/bitops.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
#include <uapi/linux/kernel.h>
1010

11-
#define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE)
1211
#define BITS_TO_LONGS(nr) __KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(long))
1312
#define BITS_TO_U64(nr) __KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(u64))
1413
#define BITS_TO_U32(nr) __KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(u32))

include/linux/bits.h

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,76 @@
1212
#define BIT_ULL_MASK(nr) (ULL(1) << ((nr) % BITS_PER_LONG_LONG))
1313
#define BIT_ULL_WORD(nr) ((nr) / BITS_PER_LONG_LONG)
1414
#define BITS_PER_BYTE 8
15+
#define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE)
1516

1617
/*
1718
* Create a contiguous bitmask starting at bit position @l and ending at
1819
* position @h. For example
1920
* GENMASK_ULL(39, 21) gives us the 64bit vector 0x000000ffffe00000.
2021
*/
2122
#if !defined(__ASSEMBLY__)
23+
24+
/*
25+
* Missing asm support
26+
*
27+
* GENMASK_U*() and BIT_U*() depend on BITS_PER_TYPE() which relies on sizeof(),
28+
* something not available in asm. Nevertheless, fixed width integers is a C
29+
* concept. Assembly code can rely on the long and long long versions instead.
30+
*/
31+
2232
#include <linux/build_bug.h>
2333
#include <linux/compiler.h>
34+
#include <linux/overflow.h>
35+
2436
#define GENMASK_INPUT_CHECK(h, l) BUILD_BUG_ON_ZERO(const_true((l) > (h)))
25-
#else
37+
38+
/*
39+
* Generate a mask for the specified type @t. Additional checks are made to
40+
* guarantee the value returned fits in that type, relying on
41+
* -Wshift-count-overflow compiler check to detect incompatible arguments.
42+
* For example, all these create build errors or warnings:
43+
*
44+
* - GENMASK(15, 20): wrong argument order
45+
* - GENMASK(72, 15): doesn't fit unsigned long
46+
* - GENMASK_U32(33, 15): doesn't fit in a u32
47+
*/
48+
#define GENMASK_TYPE(t, h, l) \
49+
((t)(GENMASK_INPUT_CHECK(h, l) + \
50+
(type_max(t) << (l) & \
51+
type_max(t) >> (BITS_PER_TYPE(t) - 1 - (h)))))
52+
53+
#define GENMASK_U8(h, l) GENMASK_TYPE(u8, h, l)
54+
#define GENMASK_U16(h, l) GENMASK_TYPE(u16, h, l)
55+
#define GENMASK_U32(h, l) GENMASK_TYPE(u32, h, l)
56+
#define GENMASK_U64(h, l) GENMASK_TYPE(u64, h, l)
57+
58+
/*
59+
* Fixed-type variants of BIT(), with additional checks like GENMASK_TYPE(). The
60+
* following examples generate compiler warnings due to -Wshift-count-overflow:
61+
*
62+
* - BIT_U8(8)
63+
* - BIT_U32(-1)
64+
* - BIT_U32(40)
65+
*/
66+
#define BIT_INPUT_CHECK(type, nr) \
67+
BUILD_BUG_ON_ZERO(const_true((nr) >= BITS_PER_TYPE(type)))
68+
69+
#define BIT_TYPE(type, nr) ((type)(BIT_INPUT_CHECK(type, nr) + BIT_ULL(nr)))
70+
71+
#define BIT_U8(nr) BIT_TYPE(u8, nr)
72+
#define BIT_U16(nr) BIT_TYPE(u16, nr)
73+
#define BIT_U32(nr) BIT_TYPE(u32, nr)
74+
#define BIT_U64(nr) BIT_TYPE(u64, nr)
75+
76+
#else /* defined(__ASSEMBLY__) */
77+
2678
/*
2779
* BUILD_BUG_ON_ZERO is not available in h files included from asm files,
2880
* disable the input check if that is the case.
2981
*/
3082
#define GENMASK_INPUT_CHECK(h, l) 0
31-
#endif
83+
84+
#endif /* !defined(__ASSEMBLY__) */
3285

3386
#define GENMASK(h, l) \
3487
(GENMASK_INPUT_CHECK(h, l) + __GENMASK(h, l))

include/linux/build_bug.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,17 @@
44

55
#include <linux/compiler.h>
66

7-
#ifdef __CHECKER__
8-
#define BUILD_BUG_ON_ZERO(e) (0)
9-
#else /* __CHECKER__ */
107
/*
118
* Force a compilation error if condition is true, but also produce a
129
* result (of value 0 and type int), so the expression can be used
1310
* e.g. in a structure initializer (or where-ever else comma expressions
1411
* aren't permitted).
12+
*
13+
* Take an error message as an optional second argument. If omitted,
14+
* default to the stringification of the tested expression.
1515
*/
16-
#define BUILD_BUG_ON_ZERO(e) ((int)(sizeof(struct { int:(-!!(e)); })))
17-
#endif /* __CHECKER__ */
16+
#define BUILD_BUG_ON_ZERO(e, ...) \
17+
__BUILD_BUG_ON_ZERO_MSG(e, ##__VA_ARGS__, #e " is true")
1818

1919
/* Force a compilation error if a constant expression is not a power of 2 */
2020
#define __BUILD_BUG_ON_NOT_POWER_OF_2(n) \

include/linux/compiler.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,9 +192,9 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
192192
})
193193

194194
#ifdef __CHECKER__
195-
#define __BUILD_BUG_ON_ZERO_MSG(e, msg) (0)
195+
#define __BUILD_BUG_ON_ZERO_MSG(e, msg, ...) (0)
196196
#else /* __CHECKER__ */
197-
#define __BUILD_BUG_ON_ZERO_MSG(e, msg) ((int)sizeof(struct {_Static_assert(!(e), msg);}))
197+
#define __BUILD_BUG_ON_ZERO_MSG(e, msg, ...) ((int)sizeof(struct {_Static_assert(!(e), msg);}))
198198
#endif /* __CHECKER__ */
199199

200200
/* &a[0] degrades to a pointer: a different type from an array */

include/linux/cpumask.h

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -625,22 +625,6 @@ static __always_inline void __cpumask_clear_cpu(int cpu, struct cpumask *dstp)
625625
__clear_bit(cpumask_check(cpu), cpumask_bits(dstp));
626626
}
627627

628-
/**
629-
* cpumask_assign_cpu - assign a cpu in a cpumask
630-
* @cpu: cpu number (< nr_cpu_ids)
631-
* @dstp: the cpumask pointer
632-
* @bool: the value to assign
633-
*/
634-
static __always_inline void cpumask_assign_cpu(int cpu, struct cpumask *dstp, bool value)
635-
{
636-
assign_bit(cpumask_check(cpu), cpumask_bits(dstp), value);
637-
}
638-
639-
static __always_inline void __cpumask_assign_cpu(int cpu, struct cpumask *dstp, bool value)
640-
{
641-
__assign_bit(cpumask_check(cpu), cpumask_bits(dstp), value);
642-
}
643-
644628
/**
645629
* cpumask_test_cpu - test for a cpu in a cpumask
646630
* @cpu: cpu number (< nr_cpu_ids)
@@ -1141,6 +1125,9 @@ void init_cpu_possible(const struct cpumask *src);
11411125
#define assign_cpu(cpu, mask, val) \
11421126
assign_bit(cpumask_check(cpu), cpumask_bits(mask), (val))
11431127

1128+
#define __assign_cpu(cpu, mask, val) \
1129+
__assign_bit(cpumask_check(cpu), cpumask_bits(mask), (val))
1130+
11441131
#define set_cpu_possible(cpu, possible) assign_cpu((cpu), &__cpu_possible_mask, (possible))
11451132
#define set_cpu_enabled(cpu, enabled) assign_cpu((cpu), &__cpu_enabled_mask, (enabled))
11461133
#define set_cpu_present(cpu, present) assign_cpu((cpu), &__cpu_present_mask, (present))

include/linux/nodemask.h

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,6 @@
3939
* int nodes_full(mask) Is mask full (all bits sets)?
4040
* int nodes_weight(mask) Hamming weight - number of set bits
4141
*
42-
* void nodes_shift_right(dst, src, n) Shift right
43-
* void nodes_shift_left(dst, src, n) Shift left
44-
*
4542
* unsigned int first_node(mask) Number lowest set bit, or MAX_NUMNODES
4643
* unsigend int next_node(node, mask) Next node past 'node', or MAX_NUMNODES
4744
* unsigned int next_node_in(node, mask) Next node past 'node', or wrap to first,
@@ -247,22 +244,6 @@ static __always_inline int __nodes_weight(const nodemask_t *srcp, unsigned int n
247244
return bitmap_weight(srcp->bits, nbits);
248245
}
249246

250-
#define nodes_shift_right(dst, src, n) \
251-
__nodes_shift_right(&(dst), &(src), (n), MAX_NUMNODES)
252-
static __always_inline void __nodes_shift_right(nodemask_t *dstp,
253-
const nodemask_t *srcp, int n, int nbits)
254-
{
255-
bitmap_shift_right(dstp->bits, srcp->bits, n, nbits);
256-
}
257-
258-
#define nodes_shift_left(dst, src, n) \
259-
__nodes_shift_left(&(dst), &(src), (n), MAX_NUMNODES)
260-
static __always_inline void __nodes_shift_left(nodemask_t *dstp,
261-
const nodemask_t *srcp, int n, int nbits)
262-
{
263-
bitmap_shift_left(dstp->bits, srcp->bits, n, nbits);
264-
}
265-
266247
/* FIXME: better would be to fix all architectures to never return
267248
> MAX_NUMNODES, then the silly min_ts could be dropped. */
268249

@@ -541,6 +522,7 @@ static __always_inline int node_random(const nodemask_t *maskp)
541522

542523
#define for_each_node(node) for_each_node_state(node, N_POSSIBLE)
543524
#define for_each_online_node(node) for_each_node_state(node, N_ONLINE)
525+
#define for_each_node_with_cpus(node) for_each_node_state(node, N_CPU)
544526

545527
/*
546528
* For nodemask scratch area.

0 commit comments

Comments
 (0)