2024-01-24 05:02:41

by Lucas De Marchi

[permalink] [raw]
Subject: [PATCH 0/3] Fixed-type GENMASK/BIT

Move the implementation of REG_GENMASK/REG_BIT to a more appropriate
place to be shared by i915, xe and possibly other parts of the kernel.

For now this re-defines the old macros. In future we may start using the
new macros directly, but that's a more intrusive search-and-replace.

Yury, I added a little bit more information to the commit message in
patch 1. First 2 patches may go through your tree. For the last one we
may have potential conflicts, so I'm not sure. +Jani from i915 side to
chime in.

v1: https://lore.kernel.org/intel-xe/[email protected]/

Lucas De Marchi (2):
bits: Introduce fixed-type BIT
drm/i915: Convert REG_GENMASK* to fixed-width GENMASK_*

Yury Norov (1):
bits: introduce fixed-type genmasks

drivers/gpu/drm/i915/i915_reg_defs.h | 108 +++------------------------
include/linux/bitops.h | 1 -
include/linux/bits.h | 33 +++++---
3 files changed, 33 insertions(+), 109 deletions(-)

--
2.43.0



2024-01-24 05:02:46

by Lucas De Marchi

[permalink] [raw]
Subject: [PATCH 2/3] bits: Introduce fixed-type BIT

Implement fixed-type BIT() to help drivers add stricter checks, like was
done for GENMASK.

Signed-off-by: Lucas De Marchi <[email protected]>
---
include/linux/bits.h | 9 +++++++++
1 file changed, 9 insertions(+)

diff --git a/include/linux/bits.h b/include/linux/bits.h
index cb94128171b2..5754a1251078 100644
--- a/include/linux/bits.h
+++ b/include/linux/bits.h
@@ -24,12 +24,16 @@
#define GENMASK_INPUT_CHECK(h, l) \
(BUILD_BUG_ON_ZERO(__builtin_choose_expr( \
__is_constexpr((l) > (h)), (l) > (h), 0)))
+#define BIT_INPUT_CHECK(type, b) \
+ ((BUILD_BUG_ON_ZERO(__builtin_choose_expr( \
+ __is_constexpr(b), (b) >= BITS_PER_TYPE(type), 0))))
#else
/*
* BUILD_BUG_ON_ZERO is not available in h files included from asm files,
* disable the input check if that is the case.
*/
#define GENMASK_INPUT_CHECK(h, l) 0
+#define BIT_INPUT_CHECK(type, b) 0
#endif

#define __GENMASK(t, h, l) \
@@ -44,4 +48,9 @@
#define GENMASK_U32(h, l) __GENMASK(u32, h, l)
#define GENMASK_U64(h, l) __GENMASK(u64, h, l)

+#define BIT_U8(b) ((u8)(BIT_INPUT_CHECK(u8, b) + BIT(b)))
+#define BIT_U16(b) ((u16)(BIT_INPUT_CHECK(u16, b) + BIT(b)))
+#define BIT_U32(b) ((u32)(BIT_INPUT_CHECK(u32, b) + BIT(b)))
+#define BIT_U64(b) ((u64)(BIT_INPUT_CHECK(u64, b) + BIT(b)))
+
#endif /* __LINUX_BITS_H */
--
2.43.0


2024-01-24 05:02:56

by Lucas De Marchi

[permalink] [raw]
Subject: [PATCH 1/3] bits: introduce fixed-type genmasks

From: Yury Norov <[email protected]>

Generalize __GENMASK() to support different types, and implement
fixed-types versions of GENMASK() based on it. The fixed-type version
allows more strict checks to the min/max values accepted, which is
useful for defining registers like implemented by i915 and xe drivers
with their REG_GENMASK*() macros.

Signed-off-by: Yury Norov <[email protected]>
---
include/linux/bitops.h | 1 -
include/linux/bits.h | 22 ++++++++++++----------
2 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index 2ba557e067fe..1db50c69cfdb 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -15,7 +15,6 @@
# define aligned_byte_mask(n) (~0xffUL << (BITS_PER_LONG - 8 - 8*(n)))
#endif

-#define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE)
#define BITS_TO_LONGS(nr) __KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(long))
#define BITS_TO_U64(nr) __KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(u64))
#define BITS_TO_U32(nr) __KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(u32))
diff --git a/include/linux/bits.h b/include/linux/bits.h
index 7c0cf5031abe..cb94128171b2 100644
--- a/include/linux/bits.h
+++ b/include/linux/bits.h
@@ -6,6 +6,8 @@
#include <vdso/bits.h>
#include <asm/bitsperlong.h>

+#define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE)
+
#define BIT_MASK(nr) (UL(1) << ((nr) % BITS_PER_LONG))
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
#define BIT_ULL_MASK(nr) (ULL(1) << ((nr) % BITS_PER_LONG_LONG))
@@ -30,16 +32,16 @@
#define GENMASK_INPUT_CHECK(h, l) 0
#endif

-#define __GENMASK(h, l) \
- (((~UL(0)) - (UL(1) << (l)) + 1) & \
- (~UL(0) >> (BITS_PER_LONG - 1 - (h))))
-#define GENMASK(h, l) \
- (GENMASK_INPUT_CHECK(h, l) + __GENMASK(h, l))
+#define __GENMASK(t, h, l) \
+ (GENMASK_INPUT_CHECK(h, l) + \
+ (((t)~0ULL - ((t)(1) << (l)) + 1) & \
+ ((t)~0ULL >> (BITS_PER_TYPE(t) - 1 - (h)))))

-#define __GENMASK_ULL(h, l) \
- (((~ULL(0)) - (ULL(1) << (l)) + 1) & \
- (~ULL(0) >> (BITS_PER_LONG_LONG - 1 - (h))))
-#define GENMASK_ULL(h, l) \
- (GENMASK_INPUT_CHECK(h, l) + __GENMASK_ULL(h, l))
+#define GENMASK(h, l) __GENMASK(unsigned long, h, l)
+#define GENMASK_ULL(h, l) __GENMASK(unsigned long long, h, l)
+#define GENMASK_U8(h, l) __GENMASK(u8, h, l)
+#define GENMASK_U16(h, l) __GENMASK(u16, h, l)
+#define GENMASK_U32(h, l) __GENMASK(u32, h, l)
+#define GENMASK_U64(h, l) __GENMASK(u64, h, l)

#endif /* __LINUX_BITS_H */
--
2.43.0


2024-01-24 05:03:12

by Lucas De Marchi

[permalink] [raw]
Subject: [PATCH 3/3] drm/i915: Convert REG_GENMASK* to fixed-width GENMASK_*

Now that include/linux/bits.h implements fixed-width GENMASK_*, use them
to implement the i915/xe specific macros. Converting each driver to use
the generic macros are left for later, when/if other driver-specific
macros are also generalized.

Signed-off-by: Lucas De Marchi <[email protected]>
---
drivers/gpu/drm/i915/i915_reg_defs.h | 108 +++------------------------
1 file changed, 11 insertions(+), 97 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg_defs.h b/drivers/gpu/drm/i915/i915_reg_defs.h
index a685db1e815d..52f99eb96f86 100644
--- a/drivers/gpu/drm/i915/i915_reg_defs.h
+++ b/drivers/gpu/drm/i915/i915_reg_defs.h
@@ -9,76 +9,19 @@
#include <linux/bitfield.h>
#include <linux/bits.h>

-/**
- * REG_BIT() - Prepare a u32 bit value
- * @__n: 0-based bit number
- *
- * Local wrapper for BIT() to force u32, with compile time checks.
- *
- * @return: Value with bit @__n set.
- */
-#define REG_BIT(__n) \
- ((u32)(BIT(__n) + \
- BUILD_BUG_ON_ZERO(__is_constexpr(__n) && \
- ((__n) < 0 || (__n) > 31))))
-
-/**
- * REG_BIT8() - Prepare a u8 bit value
- * @__n: 0-based bit number
- *
- * Local wrapper for BIT() to force u8, with compile time checks.
- *
- * @return: Value with bit @__n set.
- */
-#define REG_BIT8(__n) \
- ((u8)(BIT(__n) + \
- BUILD_BUG_ON_ZERO(__is_constexpr(__n) && \
- ((__n) < 0 || (__n) > 7))))
-
-/**
- * REG_GENMASK() - Prepare a continuous u32 bitmask
- * @__high: 0-based high bit
- * @__low: 0-based low bit
- *
- * Local wrapper for GENMASK() to force u32, with compile time checks.
- *
- * @return: Continuous bitmask from @__high to @__low, inclusive.
- */
-#define REG_GENMASK(__high, __low) \
- ((u32)(GENMASK(__high, __low) + \
- BUILD_BUG_ON_ZERO(__is_constexpr(__high) && \
- __is_constexpr(__low) && \
- ((__low) < 0 || (__high) > 31 || (__low) > (__high)))))
-
-/**
- * REG_GENMASK64() - Prepare a continuous u64 bitmask
- * @__high: 0-based high bit
- * @__low: 0-based low bit
- *
- * Local wrapper for GENMASK_ULL() to force u64, with compile time checks.
- *
- * @return: Continuous bitmask from @__high to @__low, inclusive.
+/*
+ * Wrappers over the generic BIT_* and GENMASK_* implementations,
+ * for compatibility reasons with previous implementation
*/
-#define REG_GENMASK64(__high, __low) \
- ((u64)(GENMASK_ULL(__high, __low) + \
- BUILD_BUG_ON_ZERO(__is_constexpr(__high) && \
- __is_constexpr(__low) && \
- ((__low) < 0 || (__high) > 63 || (__low) > (__high)))))
+#define REG_GENMASK(__high, __low) GENMASK_U32(__high, __low)
+#define REG_GENMASK64(__high, __low) GENMASK_U64(__high, __low)
+#define REG_GENMASK16(__high, __low) GENMASK_U16(__high, __low)
+#define REG_GENMASK8(__high, __low) GENMASK_U8(__high, __low)

-/**
- * REG_GENMASK8() - Prepare a continuous u8 bitmask
- * @__high: 0-based high bit
- * @__low: 0-based low bit
- *
- * Local wrapper for GENMASK() to force u8, with compile time checks.
- *
- * @return: Continuous bitmask from @__high to @__low, inclusive.
- */
-#define REG_GENMASK8(__high, __low) \
- ((u8)(GENMASK(__high, __low) + \
- BUILD_BUG_ON_ZERO(__is_constexpr(__high) && \
- __is_constexpr(__low) && \
- ((__low) < 0 || (__high) > 7 || (__low) > (__high)))))
+#define REG_BIT(__n) BIT_U32(__n)
+#define REG_BIT64(__n) BIT_U64(__n)
+#define REG_BIT16(__n) BIT_U16(__n)
+#define REG_BIT8(__n) BIT_U8(__n)

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

-/**
- * REG_BIT16() - Prepare a u16 bit value
- * @__n: 0-based bit number
- *
- * Local wrapper for BIT() to force u16, with compile time
- * checks.
- *
- * @return: Value with bit @__n set.
- */
-#define REG_BIT16(__n) \
- ((u16)(BIT(__n) + \
- BUILD_BUG_ON_ZERO(__is_constexpr(__n) && \
- ((__n) < 0 || (__n) > 15))))
-
-/**
- * REG_GENMASK16() - Prepare a continuous u8 bitmask
- * @__high: 0-based high bit
- * @__low: 0-based low bit
- *
- * Local wrapper for GENMASK() to force u16, with compile time
- * checks.
- *
- * @return: Continuous bitmask from @__high to @__low, inclusive.
- */
-#define REG_GENMASK16(__high, __low) \
- ((u16)(GENMASK(__high, __low) + \
- BUILD_BUG_ON_ZERO(__is_constexpr(__high) && \
- __is_constexpr(__low) && \
- ((__low) < 0 || (__high) > 15 || (__low) > (__high)))))

/**
* REG_FIELD_PREP16() - Prepare a u16 bitfield value
--
2.43.0


2024-01-24 07:59:05

by Jani Nikula

[permalink] [raw]
Subject: Re: [PATCH 1/3] bits: introduce fixed-type genmasks

On Tue, 23 Jan 2024, Lucas De Marchi <[email protected]> wrote:
> From: Yury Norov <[email protected]>
>
> Generalize __GENMASK() to support different types, and implement
> fixed-types versions of GENMASK() based on it. The fixed-type version
> allows more strict checks to the min/max values accepted, which is
> useful for defining registers like implemented by i915 and xe drivers
> with their REG_GENMASK*() macros.

Mmh, the commit message says the fixed-type version allows more strict
checks, but none are actually added. GENMASK_INPUT_CHECK() remains the
same.

Compared to the i915 and xe versions, this is more lax now. You could
specify GENMASK_U32(63,32) without complaints.


BR,
Jani.

>
> Signed-off-by: Yury Norov <[email protected]>
> ---
> include/linux/bitops.h | 1 -
> include/linux/bits.h | 22 ++++++++++++----------
> 2 files changed, 12 insertions(+), 11 deletions(-)
>
> diff --git a/include/linux/bitops.h b/include/linux/bitops.h
> index 2ba557e067fe..1db50c69cfdb 100644
> --- a/include/linux/bitops.h
> +++ b/include/linux/bitops.h
> @@ -15,7 +15,6 @@
> # define aligned_byte_mask(n) (~0xffUL << (BITS_PER_LONG - 8 - 8*(n)))
> #endif
>
> -#define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE)
> #define BITS_TO_LONGS(nr) __KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(long))
> #define BITS_TO_U64(nr) __KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(u64))
> #define BITS_TO_U32(nr) __KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(u32))
> diff --git a/include/linux/bits.h b/include/linux/bits.h
> index 7c0cf5031abe..cb94128171b2 100644
> --- a/include/linux/bits.h
> +++ b/include/linux/bits.h
> @@ -6,6 +6,8 @@
> #include <vdso/bits.h>
> #include <asm/bitsperlong.h>
>
> +#define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE)
> +
> #define BIT_MASK(nr) (UL(1) << ((nr) % BITS_PER_LONG))
> #define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
> #define BIT_ULL_MASK(nr) (ULL(1) << ((nr) % BITS_PER_LONG_LONG))
> @@ -30,16 +32,16 @@
> #define GENMASK_INPUT_CHECK(h, l) 0
> #endif
>
> -#define __GENMASK(h, l) \
> - (((~UL(0)) - (UL(1) << (l)) + 1) & \
> - (~UL(0) >> (BITS_PER_LONG - 1 - (h))))
> -#define GENMASK(h, l) \
> - (GENMASK_INPUT_CHECK(h, l) + __GENMASK(h, l))
> +#define __GENMASK(t, h, l) \
> + (GENMASK_INPUT_CHECK(h, l) + \
> + (((t)~0ULL - ((t)(1) << (l)) + 1) & \
> + ((t)~0ULL >> (BITS_PER_TYPE(t) - 1 - (h)))))
>
> -#define __GENMASK_ULL(h, l) \
> - (((~ULL(0)) - (ULL(1) << (l)) + 1) & \
> - (~ULL(0) >> (BITS_PER_LONG_LONG - 1 - (h))))
> -#define GENMASK_ULL(h, l) \
> - (GENMASK_INPUT_CHECK(h, l) + __GENMASK_ULL(h, l))
> +#define GENMASK(h, l) __GENMASK(unsigned long, h, l)
> +#define GENMASK_ULL(h, l) __GENMASK(unsigned long long, h, l)
> +#define GENMASK_U8(h, l) __GENMASK(u8, h, l)
> +#define GENMASK_U16(h, l) __GENMASK(u16, h, l)
> +#define GENMASK_U32(h, l) __GENMASK(u32, h, l)
> +#define GENMASK_U64(h, l) __GENMASK(u64, h, l)
>
> #endif /* __LINUX_BITS_H */

--
Jani Nikula, Intel

2024-01-24 08:21:17

by Jani Nikula

[permalink] [raw]
Subject: Re: [PATCH 3/3] drm/i915: Convert REG_GENMASK* to fixed-width GENMASK_*

On Tue, 23 Jan 2024, Lucas De Marchi <[email protected]> wrote:
> Now that include/linux/bits.h implements fixed-width GENMASK_*, use them
> to implement the i915/xe specific macros. Converting each driver to use
> the generic macros are left for later, when/if other driver-specific
> macros are also generalized.

With the type-specific max checks added to GENMASK_*, this would be
great.

BR,
Jani.

>
> Signed-off-by: Lucas De Marchi <[email protected]>
> ---
> drivers/gpu/drm/i915/i915_reg_defs.h | 108 +++------------------------
> 1 file changed, 11 insertions(+), 97 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_reg_defs.h b/drivers/gpu/drm/i915/i915_reg_defs.h
> index a685db1e815d..52f99eb96f86 100644
> --- a/drivers/gpu/drm/i915/i915_reg_defs.h
> +++ b/drivers/gpu/drm/i915/i915_reg_defs.h
> @@ -9,76 +9,19 @@
> #include <linux/bitfield.h>
> #include <linux/bits.h>
>
> -/**
> - * REG_BIT() - Prepare a u32 bit value
> - * @__n: 0-based bit number
> - *
> - * Local wrapper for BIT() to force u32, with compile time checks.
> - *
> - * @return: Value with bit @__n set.
> - */
> -#define REG_BIT(__n) \
> - ((u32)(BIT(__n) + \
> - BUILD_BUG_ON_ZERO(__is_constexpr(__n) && \
> - ((__n) < 0 || (__n) > 31))))
> -
> -/**
> - * REG_BIT8() - Prepare a u8 bit value
> - * @__n: 0-based bit number
> - *
> - * Local wrapper for BIT() to force u8, with compile time checks.
> - *
> - * @return: Value with bit @__n set.
> - */
> -#define REG_BIT8(__n) \
> - ((u8)(BIT(__n) + \
> - BUILD_BUG_ON_ZERO(__is_constexpr(__n) && \
> - ((__n) < 0 || (__n) > 7))))
> -
> -/**
> - * REG_GENMASK() - Prepare a continuous u32 bitmask
> - * @__high: 0-based high bit
> - * @__low: 0-based low bit
> - *
> - * Local wrapper for GENMASK() to force u32, with compile time checks.
> - *
> - * @return: Continuous bitmask from @__high to @__low, inclusive.
> - */
> -#define REG_GENMASK(__high, __low) \
> - ((u32)(GENMASK(__high, __low) + \
> - BUILD_BUG_ON_ZERO(__is_constexpr(__high) && \
> - __is_constexpr(__low) && \
> - ((__low) < 0 || (__high) > 31 || (__low) > (__high)))))
> -
> -/**
> - * REG_GENMASK64() - Prepare a continuous u64 bitmask
> - * @__high: 0-based high bit
> - * @__low: 0-based low bit
> - *
> - * Local wrapper for GENMASK_ULL() to force u64, with compile time checks.
> - *
> - * @return: Continuous bitmask from @__high to @__low, inclusive.
> +/*
> + * Wrappers over the generic BIT_* and GENMASK_* implementations,
> + * for compatibility reasons with previous implementation
> */
> -#define REG_GENMASK64(__high, __low) \
> - ((u64)(GENMASK_ULL(__high, __low) + \
> - BUILD_BUG_ON_ZERO(__is_constexpr(__high) && \
> - __is_constexpr(__low) && \
> - ((__low) < 0 || (__high) > 63 || (__low) > (__high)))))
> +#define REG_GENMASK(__high, __low) GENMASK_U32(__high, __low)
> +#define REG_GENMASK64(__high, __low) GENMASK_U64(__high, __low)
> +#define REG_GENMASK16(__high, __low) GENMASK_U16(__high, __low)
> +#define REG_GENMASK8(__high, __low) GENMASK_U8(__high, __low)
>
> -/**
> - * REG_GENMASK8() - Prepare a continuous u8 bitmask
> - * @__high: 0-based high bit
> - * @__low: 0-based low bit
> - *
> - * Local wrapper for GENMASK() to force u8, with compile time checks.
> - *
> - * @return: Continuous bitmask from @__high to @__low, inclusive.
> - */
> -#define REG_GENMASK8(__high, __low) \
> - ((u8)(GENMASK(__high, __low) + \
> - BUILD_BUG_ON_ZERO(__is_constexpr(__high) && \
> - __is_constexpr(__low) && \
> - ((__low) < 0 || (__high) > 7 || (__low) > (__high)))))
> +#define REG_BIT(__n) BIT_U32(__n)
> +#define REG_BIT64(__n) BIT_U64(__n)
> +#define REG_BIT16(__n) BIT_U16(__n)
> +#define REG_BIT8(__n) BIT_U8(__n)
>
> /*
> * Local integer constant expression version of is_power_of_2().
> @@ -143,35 +86,6 @@
> */
> #define REG_FIELD_GET64(__mask, __val) ((u64)FIELD_GET(__mask, __val))
>
> -/**
> - * REG_BIT16() - Prepare a u16 bit value
> - * @__n: 0-based bit number
> - *
> - * Local wrapper for BIT() to force u16, with compile time
> - * checks.
> - *
> - * @return: Value with bit @__n set.
> - */
> -#define REG_BIT16(__n) \
> - ((u16)(BIT(__n) + \
> - BUILD_BUG_ON_ZERO(__is_constexpr(__n) && \
> - ((__n) < 0 || (__n) > 15))))
> -
> -/**
> - * REG_GENMASK16() - Prepare a continuous u8 bitmask
> - * @__high: 0-based high bit
> - * @__low: 0-based low bit
> - *
> - * Local wrapper for GENMASK() to force u16, with compile time
> - * checks.
> - *
> - * @return: Continuous bitmask from @__high to @__low, inclusive.
> - */
> -#define REG_GENMASK16(__high, __low) \
> - ((u16)(GENMASK(__high, __low) + \
> - BUILD_BUG_ON_ZERO(__is_constexpr(__high) && \
> - __is_constexpr(__low) && \
> - ((__low) < 0 || (__high) > 15 || (__low) > (__high)))))
>
> /**
> * REG_FIELD_PREP16() - Prepare a u16 bitfield value

--
Jani Nikula, Intel

2024-01-24 14:06:50

by Lucas De Marchi

[permalink] [raw]
Subject: Re: Re: [PATCH 1/3] bits: introduce fixed-type genmasks

On Wed, Jan 24, 2024 at 09:58:26AM +0200, Jani Nikula wrote:
>On Tue, 23 Jan 2024, Lucas De Marchi <[email protected]> wrote:
>> From: Yury Norov <[email protected]>
>>
>> Generalize __GENMASK() to support different types, and implement
>> fixed-types versions of GENMASK() based on it. The fixed-type version
>> allows more strict checks to the min/max values accepted, which is
>> useful for defining registers like implemented by i915 and xe drivers
>> with their REG_GENMASK*() macros.
>
>Mmh, the commit message says the fixed-type version allows more strict
>checks, but none are actually added. GENMASK_INPUT_CHECK() remains the
>same.
>
>Compared to the i915 and xe versions, this is more lax now. You could
>specify GENMASK_U32(63,32) without complaints.

Doing this on top of the this series:

-#define XELPDP_PORT_M2P_COMMAND_TYPE_MASK REG_GENMASK(30, 27)
+#define XELPDP_PORT_M2P_COMMAND_TYPE_MASK REG_GENMASK(62, 32)

and I do get a build failure:

./drivers/gpu/drm/i915/display/intel_cx0_phy.c: In function ‘__intel_cx0_read_once’:
./include/linux/bits.h:41:31: error: left shift count >= width of type [-Werror=shift-count-overflow]
41 | (((t)~0ULL - ((t)(1) << (l)) + 1) & \
| ^~


I also tested them individually. All of these fail to build for me:

1)
-#define XELPDP_PORT_M2P_COMMAND_TYPE_MASK REG_GENMASK(30, 27)
+#define XELPDP_PORT_M2P_COMMAND_TYPE_MASK REG_GENMASK(32, 27)

2)
-#define XELPDP_PORT_M2P_COMMAND_TYPE_MASK REG_GENMASK(30, 27)
+#define XELPDP_PORT_M2P_COMMAND_TYPE_MASK REG_GENMASK(30, 31)

3)
-#define XELPDP_PORT_M2P_COMMAND_TYPE_MASK REG_GENMASK(30, 27)
+#define XELPDP_PORT_M2P_COMMAND_TYPE_MASK REG_GENMASK(30, -1)


Lucas De Marchi

2024-01-24 15:28:28

by Yury Norov

[permalink] [raw]
Subject: Re: Re: [PATCH 1/3] bits: introduce fixed-type genmasks

On Wed, Jan 24, 2024 at 08:03:53AM -0600, Lucas De Marchi wrote:
> On Wed, Jan 24, 2024 at 09:58:26AM +0200, Jani Nikula wrote:
> > On Tue, 23 Jan 2024, Lucas De Marchi <[email protected]> wrote:
> > > From: Yury Norov <[email protected]>
> > >
> > > Generalize __GENMASK() to support different types, and implement
> > > fixed-types versions of GENMASK() based on it. The fixed-type version
> > > allows more strict checks to the min/max values accepted, which is
> > > useful for defining registers like implemented by i915 and xe drivers
> > > with their REG_GENMASK*() macros.
> >
> > Mmh, the commit message says the fixed-type version allows more strict
> > checks, but none are actually added. GENMASK_INPUT_CHECK() remains the
> > same.
> >
> > Compared to the i915 and xe versions, this is more lax now. You could
> > specify GENMASK_U32(63,32) without complaints.
>
> Doing this on top of the this series:
>
> -#define XELPDP_PORT_M2P_COMMAND_TYPE_MASK REG_GENMASK(30, 27)
> +#define XELPDP_PORT_M2P_COMMAND_TYPE_MASK REG_GENMASK(62, 32)
>
> and I do get a build failure:
>
> ../drivers/gpu/drm/i915/display/intel_cx0_phy.c: In function ‘__intel_cx0_read_once’:
> ../include/linux/bits.h:41:31: error: left shift count >= width of type [-Werror=shift-count-overflow]
> 41 | (((t)~0ULL - ((t)(1) << (l)) + 1) & \
> | ^~

I would better include this in commit message to avoid people's
confusion. If it comes to v2, can you please do it and mention that
this trick relies on shift-count-overflow compiler check?

Thanks,
Yury

2024-01-24 16:24:39

by Gustavo Sousa

[permalink] [raw]
Subject: Re: Re: [PATCH 1/3] bits: introduce fixed-type genmasks

Quoting Yury Norov (2024-01-24 12:27:58-03:00)
>On Wed, Jan 24, 2024 at 08:03:53AM -0600, Lucas De Marchi wrote:
>> On Wed, Jan 24, 2024 at 09:58:26AM +0200, Jani Nikula wrote:
>> > On Tue, 23 Jan 2024, Lucas De Marchi <[email protected]> wrote:
>> > > From: Yury Norov <[email protected]>
>> > >
>> > > Generalize __GENMASK() to support different types, and implement
>> > > fixed-types versions of GENMASK() based on it. The fixed-type version
>> > > allows more strict checks to the min/max values accepted, which is
>> > > useful for defining registers like implemented by i915 and xe drivers
>> > > with their REG_GENMASK*() macros.
>> >
>> > Mmh, the commit message says the fixed-type version allows more strict
>> > checks, but none are actually added. GENMASK_INPUT_CHECK() remains the
>> > same.
>> >
>> > Compared to the i915 and xe versions, this is more lax now. You could
>> > specify GENMASK_U32(63,32) without complaints.
>>
>> Doing this on top of the this series:
>>
>> -#define XELPDP_PORT_M2P_COMMAND_TYPE_MASK REG_GENMASK(30, 27)
>> +#define XELPDP_PORT_M2P_COMMAND_TYPE_MASK REG_GENMASK(62, 32)
>>
>> and I do get a build failure:
>>
>> ../drivers/gpu/drm/i915/display/intel_cx0_phy.c: In function ‘__intel_cx0_read_once’:
>> ../include/linux/bits.h:41:31: error: left shift count >= width of type [-Werror=shift-count-overflow]
>> 41 | (((t)~0ULL - ((t)(1) << (l)) + 1) & \
>> | ^~
>
>I would better include this in commit message to avoid people's
>confusion. If it comes to v2, can you please do it and mention that
>this trick relies on shift-count-overflow compiler check?

Wouldn't it be better to have explicit check that l and h are not out of bounds
based on BITS_PER_TYPE() than relying on a compiler flag that could be turned
off (maybe for some questionable reason, but even so)?

--
Gustavo Sousa

2024-01-25 10:00:20

by Jani Nikula

[permalink] [raw]
Subject: Re: Re: [PATCH 1/3] bits: introduce fixed-type genmasks

On Wed, 24 Jan 2024, Gustavo Sousa <[email protected]> wrote:
> Quoting Yury Norov (2024-01-24 12:27:58-03:00)
>>On Wed, Jan 24, 2024 at 08:03:53AM -0600, Lucas De Marchi wrote:
>>> On Wed, Jan 24, 2024 at 09:58:26AM +0200, Jani Nikula wrote:
>>> > On Tue, 23 Jan 2024, Lucas De Marchi <[email protected]> wrote:
>>> > > From: Yury Norov <[email protected]>
>>> > >
>>> > > Generalize __GENMASK() to support different types, and implement
>>> > > fixed-types versions of GENMASK() based on it. The fixed-type version
>>> > > allows more strict checks to the min/max values accepted, which is
>>> > > useful for defining registers like implemented by i915 and xe drivers
>>> > > with their REG_GENMASK*() macros.
>>> >
>>> > Mmh, the commit message says the fixed-type version allows more strict
>>> > checks, but none are actually added. GENMASK_INPUT_CHECK() remains the
>>> > same.
>>> >
>>> > Compared to the i915 and xe versions, this is more lax now. You could
>>> > specify GENMASK_U32(63,32) without complaints.
>>>
>>> Doing this on top of the this series:
>>>
>>> -#define XELPDP_PORT_M2P_COMMAND_TYPE_MASK REG_GENMASK(30, 27)
>>> +#define XELPDP_PORT_M2P_COMMAND_TYPE_MASK REG_GENMASK(62, 32)
>>>
>>> and I do get a build failure:
>>>
>>> ../drivers/gpu/drm/i915/display/intel_cx0_phy.c: In function ‘__intel_cx0_read_once’:
>>> ../include/linux/bits.h:41:31: error: left shift count >= width of type [-Werror=shift-count-overflow]
>>> 41 | (((t)~0ULL - ((t)(1) << (l)) + 1) & \
>>> | ^~

I stand corrected.

>>
>>I would better include this in commit message to avoid people's
>>confusion. If it comes to v2, can you please do it and mention that
>>this trick relies on shift-count-overflow compiler check?
>
> Wouldn't it be better to have explicit check that l and h are not out of bounds
> based on BITS_PER_TYPE() than relying on a compiler flag that could be turned
> off (maybe for some questionable reason, but even so)?

My preference would be the explicit check, a comment in code, or an
explanation in the commit message, in this order. Because honestly, none
of this is obvious, and a future refactoring of GENMASK might just
inadvertently thwart the whole check.

Regardless, my main concern was moot, on the series,

Acked-by: Jani Nikula <[email protected]>


--
Jani Nikula, Intel

2024-01-29 14:51:02

by Lucas De Marchi

[permalink] [raw]
Subject: Re: Re: Re: [PATCH 1/3] bits: introduce fixed-type genmasks

On Wed, Jan 24, 2024 at 07:27:58AM -0800, Yury Norov wrote:
>On Wed, Jan 24, 2024 at 08:03:53AM -0600, Lucas De Marchi wrote:
>> On Wed, Jan 24, 2024 at 09:58:26AM +0200, Jani Nikula wrote:
>> > On Tue, 23 Jan 2024, Lucas De Marchi <[email protected]> wrote:
>> > > From: Yury Norov <[email protected]>
>> > >
>> > > Generalize __GENMASK() to support different types, and implement
>> > > fixed-types versions of GENMASK() based on it. The fixed-type version
>> > > allows more strict checks to the min/max values accepted, which is
>> > > useful for defining registers like implemented by i915 and xe drivers
>> > > with their REG_GENMASK*() macros.
>> >
>> > Mmh, the commit message says the fixed-type version allows more strict
>> > checks, but none are actually added. GENMASK_INPUT_CHECK() remains the
>> > same.
>> >
>> > Compared to the i915 and xe versions, this is more lax now. You could
>> > specify GENMASK_U32(63,32) without complaints.
>>
>> Doing this on top of the this series:
>>
>> -#define XELPDP_PORT_M2P_COMMAND_TYPE_MASK REG_GENMASK(30, 27)
>> +#define XELPDP_PORT_M2P_COMMAND_TYPE_MASK REG_GENMASK(62, 32)
>>
>> and I do get a build failure:
>>
>> ../drivers/gpu/drm/i915/display/intel_cx0_phy.c: In function ‘__intel_cx0_read_once’:
>> ../include/linux/bits.h:41:31: error: left shift count >= width of type [-Werror=shift-count-overflow]
>> 41 | (((t)~0ULL - ((t)(1) << (l)) + 1) & \
>> | ^~
>
>I would better include this in commit message to avoid people's
>confusion. If it comes to v2, can you please do it and mention that
>this trick relies on shift-count-overflow compiler check?

either that or an explicit check as it was suggested. What's your
preference?

Lucas De Marchi

>
>Thanks,
>Yury

2024-01-29 15:11:30

by Yury Norov

[permalink] [raw]
Subject: Re: Re: Re: [PATCH 1/3] bits: introduce fixed-type genmasks

On Mon, Jan 29, 2024 at 08:49:35AM -0600, Lucas De Marchi wrote:
> On Wed, Jan 24, 2024 at 07:27:58AM -0800, Yury Norov wrote:
> > On Wed, Jan 24, 2024 at 08:03:53AM -0600, Lucas De Marchi wrote:
> > > On Wed, Jan 24, 2024 at 09:58:26AM +0200, Jani Nikula wrote:
> > > > On Tue, 23 Jan 2024, Lucas De Marchi <[email protected]> wrote:
> > > > > From: Yury Norov <[email protected]>
> > > > >
> > > > > Generalize __GENMASK() to support different types, and implement
> > > > > fixed-types versions of GENMASK() based on it. The fixed-type version
> > > > > allows more strict checks to the min/max values accepted, which is
> > > > > useful for defining registers like implemented by i915 and xe drivers
> > > > > with their REG_GENMASK*() macros.
> > > >
> > > > Mmh, the commit message says the fixed-type version allows more strict
> > > > checks, but none are actually added. GENMASK_INPUT_CHECK() remains the
> > > > same.
> > > >
> > > > Compared to the i915 and xe versions, this is more lax now. You could
> > > > specify GENMASK_U32(63,32) without complaints.
> > >
> > > Doing this on top of the this series:
> > >
> > > -#define XELPDP_PORT_M2P_COMMAND_TYPE_MASK REG_GENMASK(30, 27)
> > > +#define XELPDP_PORT_M2P_COMMAND_TYPE_MASK REG_GENMASK(62, 32)
> > >
> > > and I do get a build failure:
> > >
> > > ../drivers/gpu/drm/i915/display/intel_cx0_phy.c: In function ‘__intel_cx0_read_once’:
> > > ../include/linux/bits.h:41:31: error: left shift count >= width of type [-Werror=shift-count-overflow]
> > > 41 | (((t)~0ULL - ((t)(1) << (l)) + 1) & \
> > > | ^~
> >
> > I would better include this in commit message to avoid people's
> > confusion. If it comes to v2, can you please do it and mention that
> > this trick relies on shift-count-overflow compiler check?
>
> either that or an explicit check as it was suggested. What's your
> preference?

Let's put a comment in the code. An argument that shift-count-overflow
may be disabled sounds more like a speculation unless we have a solid
example of a build system where the error is disabled for a good sane
reason, but possible GENMASK() overflow is still considered dangerous.

GENMASK() is all about bit shifts, so shift-related error is something
I'd expect when using GENMASK().

Also, the macro is widely used in the kernel:

yury:linux$ git grep GENMASK | wc -l
26879

Explicit check would add pressure on the compiler for nothing.

Thanks,
Yury

2024-02-09 16:52:18

by Yury Norov

[permalink] [raw]
Subject: Re: [PATCH 2/3] bits: Introduce fixed-type BIT

On Tue, Jan 23, 2024 at 09:02:04PM -0800, Lucas De Marchi wrote:
> Implement fixed-type BIT() to help drivers add stricter checks, like was
> done for GENMASK.
>
> Signed-off-by: Lucas De Marchi <[email protected]>

Reviewed-by: Yury Norov <[email protected]>

> ---
> include/linux/bits.h | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
> diff --git a/include/linux/bits.h b/include/linux/bits.h
> index cb94128171b2..5754a1251078 100644
> --- a/include/linux/bits.h
> +++ b/include/linux/bits.h
> @@ -24,12 +24,16 @@
> #define GENMASK_INPUT_CHECK(h, l) \
> (BUILD_BUG_ON_ZERO(__builtin_choose_expr( \
> __is_constexpr((l) > (h)), (l) > (h), 0)))
> +#define BIT_INPUT_CHECK(type, b) \
> + ((BUILD_BUG_ON_ZERO(__builtin_choose_expr( \
> + __is_constexpr(b), (b) >= BITS_PER_TYPE(type), 0))))
> #else
> /*
> * BUILD_BUG_ON_ZERO is not available in h files included from asm files,
> * disable the input check if that is the case.
> */
> #define GENMASK_INPUT_CHECK(h, l) 0
> +#define BIT_INPUT_CHECK(type, b) 0
> #endif
>
> #define __GENMASK(t, h, l) \
> @@ -44,4 +48,9 @@
> #define GENMASK_U32(h, l) __GENMASK(u32, h, l)
> #define GENMASK_U64(h, l) __GENMASK(u64, h, l)
>
> +#define BIT_U8(b) ((u8)(BIT_INPUT_CHECK(u8, b) + BIT(b)))
> +#define BIT_U16(b) ((u16)(BIT_INPUT_CHECK(u16, b) + BIT(b)))
> +#define BIT_U32(b) ((u32)(BIT_INPUT_CHECK(u32, b) + BIT(b)))
> +#define BIT_U64(b) ((u64)(BIT_INPUT_CHECK(u64, b) + BIT(b)))
> +
> #endif /* __LINUX_BITS_H */
> --
> 2.43.0