2024-02-14 21:47:38

by Michal Wajdeczko

[permalink] [raw]
Subject: [PATCH 1/2] wordpart.h: Helpers for making u16/u32/u64 values

It is quite common practice to make u16, u32 or u64 values from
smaller words. Add simple helpers for that.

Signed-off-by: Michal Wajdeczko <[email protected]>
---
v2: new macro names due to conflict with crypto/aria.h
explicit cast and truncation everywhere (Alexey)
moved to wordpart.h (Andy)
---
Cc: Kees Cook <[email protected]>
Cc: Andy Shevchenko <[email protected]>
Cc: Alexey Dobriyan <[email protected]>
Cc: Jani Nikula <[email protected]>
---
include/linux/wordpart.h | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)

diff --git a/include/linux/wordpart.h b/include/linux/wordpart.h
index f6f8f83b15b0..8c75a5355112 100644
--- a/include/linux/wordpart.h
+++ b/include/linux/wordpart.h
@@ -31,6 +31,38 @@
*/
#define lower_16_bits(n) ((u16)((n) & 0xffff))

+/**
+ * make_u16_from_u8 - make u16 value from two u8 values
+ * @hi: value representing upper 8 bits
+ * @lo: value representing lower 8 bits
+ */
+#define make_u16_from_u8(hi, lo) ((u16)((u16)(u8)(hi) << 8 | (u8)(lo)))
+
+/**
+ * make_u32_from_u16 - make u32 value from two u16 values
+ * @hi: value representing upper 16 bits
+ * @lo: value representing lower 16 bits
+ */
+#define make_u32_from_u16(hi, lo) ((u32)((u32)(u16)(hi) << 16 | (u16)(lo)))
+
+/**
+ * make_u32_from_u8 - make u32 value from u8 values
+ * @a: value representing bits 31-24
+ * @b: value representing bits 23-16
+ * @c: value representing bits 15-8
+ * @d: value representing bits 7-0
+ */
+#define make_u32_from_u8(a, b, c, d) \
+ make_u32_from_u16(make_u16_from_u8((a), (b)), \
+ make_u16_from_u8((c), (d)))
+
+/**
+ * make_u64_from_u32 - make u64 value from two u32 values
+ * @hi: value representing upper 32 bits
+ * @lo: value representing lower 32 bits
+ */
+#define make_u64_from_u32(hi, lo) ((u64)((u64)(u32)(hi) << 32 | (u32)(lo)))
+
/**
* REPEAT_BYTE - repeat the value @x multiple times as an unsigned long value
* @x: value to repeat
--
2.43.0



2024-02-14 21:47:47

by Michal Wajdeczko

[permalink] [raw]
Subject: [PATCH 2/2] drm/xe: Prefer make_u64_from_u32() over local macro

Stop using private make_u64() macro if there is a generic one.

Signed-off-by: Michal Wajdeczko <[email protected]>
---
Cc: Rodrigo Vivi <[email protected]>
Cc: Jani Nikula <[email protected]>
---
drivers/gpu/drm/xe/xe_gt_pagefault.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_gt_pagefault.c b/drivers/gpu/drm/xe/xe_gt_pagefault.c
index 59a70d2e0a7a..ac90eda39ceb 100644
--- a/drivers/gpu/drm/xe/xe_gt_pagefault.c
+++ b/drivers/gpu/drm/xe/xe_gt_pagefault.c
@@ -7,6 +7,7 @@

#include <linux/bitfield.h>
#include <linux/circ_buf.h>
+#include <linux/wordpart.h>

#include <drm/drm_exec.h>
#include <drm/drm_managed.h>
@@ -549,8 +550,6 @@ static int handle_acc(struct xe_gt *gt, struct acc *acc)
return ret;
}

-#define make_u64(hi__, low__) ((u64)(hi__) << 32 | (u64)(low__))
-
#define ACC_MSG_LEN_DW 4

static bool get_acc(struct acc_queue *acc_queue, struct acc *acc)
@@ -571,8 +570,8 @@ static bool get_acc(struct acc_queue *acc_queue, struct acc *acc)
acc->asid = FIELD_GET(ACC_ASID, desc->dw1);
acc->vfid = FIELD_GET(ACC_VFID, desc->dw2);
acc->access_type = FIELD_GET(ACC_TYPE, desc->dw0);
- acc->va_range_base = make_u64(desc->dw3 & ACC_VIRTUAL_ADDR_RANGE_HI,
- desc->dw2 & ACC_VIRTUAL_ADDR_RANGE_LO);
+ acc->va_range_base = make_u64_from_u32(desc->dw3 & ACC_VIRTUAL_ADDR_RANGE_HI,
+ desc->dw2 & ACC_VIRTUAL_ADDR_RANGE_LO);

acc_queue->head = (acc_queue->head + ACC_MSG_LEN_DW) %
ACC_QUEUE_NUM_DW;
--
2.43.0


2024-02-14 22:09:44

by Kees Cook

[permalink] [raw]
Subject: Re: [PATCH 1/2] wordpart.h: Helpers for making u16/u32/u64 values

On Wed, Feb 14, 2024 at 10:46:53PM +0100, Michal Wajdeczko wrote:
> It is quite common practice to make u16, u32 or u64 values from
> smaller words. Add simple helpers for that.
>
> Signed-off-by: Michal Wajdeczko <[email protected]>
> ---
> v2: new macro names due to conflict with crypto/aria.h
> explicit cast and truncation everywhere (Alexey)
> moved to wordpart.h (Andy)
> ---
> Cc: Kees Cook <[email protected]>
> Cc: Andy Shevchenko <[email protected]>
> Cc: Alexey Dobriyan <[email protected]>
> Cc: Jani Nikula <[email protected]>
> ---
> include/linux/wordpart.h | 32 ++++++++++++++++++++++++++++++++
> 1 file changed, 32 insertions(+)
>
> diff --git a/include/linux/wordpart.h b/include/linux/wordpart.h
> index f6f8f83b15b0..8c75a5355112 100644
> --- a/include/linux/wordpart.h
> +++ b/include/linux/wordpart.h
> @@ -31,6 +31,38 @@
> */
> #define lower_16_bits(n) ((u16)((n) & 0xffff))
>
> +/**
> + * make_u16_from_u8 - make u16 value from two u8 values
> + * @hi: value representing upper 8 bits
> + * @lo: value representing lower 8 bits
> + */
> +#define make_u16_from_u8(hi, lo) ((u16)((u16)(u8)(hi) << 8 | (u8)(lo)))

Do we want to actually do type validation here? Right now it's just
cast/truncating, which based on the version log is by design. Is silent
truncation the right thing to do?

--
Kees Cook

2024-02-15 20:41:00

by Michal Wajdeczko

[permalink] [raw]
Subject: Re: [PATCH 1/2] wordpart.h: Helpers for making u16/u32/u64 values



On 14.02.2024 23:09, Kees Cook wrote:
> On Wed, Feb 14, 2024 at 10:46:53PM +0100, Michal Wajdeczko wrote:
>> It is quite common practice to make u16, u32 or u64 values from
>> smaller words. Add simple helpers for that.
>>
>> Signed-off-by: Michal Wajdeczko <[email protected]>
>> ---
>> v2: new macro names due to conflict with crypto/aria.h
>> explicit cast and truncation everywhere (Alexey)
>> moved to wordpart.h (Andy)
>> ---
>> Cc: Kees Cook <[email protected]>
>> Cc: Andy Shevchenko <[email protected]>
>> Cc: Alexey Dobriyan <[email protected]>
>> Cc: Jani Nikula <[email protected]>
>> ---
>> include/linux/wordpart.h | 32 ++++++++++++++++++++++++++++++++
>> 1 file changed, 32 insertions(+)
>>
>> diff --git a/include/linux/wordpart.h b/include/linux/wordpart.h
>> index f6f8f83b15b0..8c75a5355112 100644
>> --- a/include/linux/wordpart.h
>> +++ b/include/linux/wordpart.h
>> @@ -31,6 +31,38 @@
>> */
>> #define lower_16_bits(n) ((u16)((n) & 0xffff))
>>
>> +/**
>> + * make_u16_from_u8 - make u16 value from two u8 values
>> + * @hi: value representing upper 8 bits
>> + * @lo: value representing lower 8 bits
>> + */
>> +#define make_u16_from_u8(hi, lo) ((u16)((u16)(u8)(hi) << 8 | (u8)(lo)))
>
> Do we want to actually do type validation here? Right now it's just
> cast/truncating, which based on the version log is by design. Is silent
> truncation the right thing to do?

note that even FIELD_PREP() is doing silent truncation and these macros
here could be treated as specialized/simplified variants of FIELD_PREP()
as alternate implementation can look like:

#define make_u16_from_u8(hi, lo) \
((u16)(FIELD_PREP_CONST(GENMASK(15, 8), (hi)) | \
FIELD_PREP_CONST(GENMASK(7, 0), (lo))))

#define make_u32_from_u16(hi, lo) \
((u32)(FIELD_PREP_CONST(GENMASK(31, 16), (hi)) | \
FIELD_PREP_CONST(GENMASK(15, 0), (lo))))

#define make_u64_from_u32(hi, lo) \
((u64)(FIELD_PREP_CONST(GENMASK_ULL(63, 32), (hi)) | \
FIELD_PREP_CONST(GENMASK_ULL(31, 0), (lo))))

but then it will not match simplicity of the lower|upper_XX_bits macros


2024-02-15 22:53:57

by Kees Cook

[permalink] [raw]
Subject: Re: [PATCH 1/2] wordpart.h: Helpers for making u16/u32/u64 values

On Thu, Feb 15, 2024 at 09:40:40PM +0100, Michal Wajdeczko wrote:
> On 14.02.2024 23:09, Kees Cook wrote:
> > On Wed, Feb 14, 2024 at 10:46:53PM +0100, Michal Wajdeczko wrote:
> >> It is quite common practice to make u16, u32 or u64 values from
> >> smaller words. Add simple helpers for that.
> >>
> >> Signed-off-by: Michal Wajdeczko <[email protected]>
> >> ---
> >> v2: new macro names due to conflict with crypto/aria.h
> >> explicit cast and truncation everywhere (Alexey)
> >> moved to wordpart.h (Andy)
> >> ---
> >> Cc: Kees Cook <[email protected]>
> >> Cc: Andy Shevchenko <[email protected]>
> >> Cc: Alexey Dobriyan <[email protected]>
> >> Cc: Jani Nikula <[email protected]>
> >> ---
> >> include/linux/wordpart.h | 32 ++++++++++++++++++++++++++++++++
> >> 1 file changed, 32 insertions(+)
> >>
> >> diff --git a/include/linux/wordpart.h b/include/linux/wordpart.h
> >> index f6f8f83b15b0..8c75a5355112 100644
> >> --- a/include/linux/wordpart.h
> >> +++ b/include/linux/wordpart.h
> >> @@ -31,6 +31,38 @@
> >> */
> >> #define lower_16_bits(n) ((u16)((n) & 0xffff))
> >>
> >> +/**
> >> + * make_u16_from_u8 - make u16 value from two u8 values
> >> + * @hi: value representing upper 8 bits
> >> + * @lo: value representing lower 8 bits
> >> + */
> >> +#define make_u16_from_u8(hi, lo) ((u16)((u16)(u8)(hi) << 8 | (u8)(lo)))
> >
> > Do we want to actually do type validation here? Right now it's just
> > cast/truncating, which based on the version log is by design. Is silent
> > truncation the right thing to do?
>
> note that even FIELD_PREP() is doing silent truncation and these macros
> here could be treated as specialized/simplified variants of FIELD_PREP()
> as alternate implementation can look like:

Also, isn't all of this endian-specific?

--
Kees Cook

2024-03-26 18:18:44

by Michal Wajdeczko

[permalink] [raw]
Subject: Re: [PATCH 1/2] wordpart.h: Helpers for making u16/u32/u64 values



On 15.02.2024 23:47, Kees Cook wrote:
> On Thu, Feb 15, 2024 at 09:40:40PM +0100, Michal Wajdeczko wrote:
>> On 14.02.2024 23:09, Kees Cook wrote:
>>> On Wed, Feb 14, 2024 at 10:46:53PM +0100, Michal Wajdeczko wrote:
>>>> It is quite common practice to make u16, u32 or u64 values from
>>>> smaller words. Add simple helpers for that.
>>>>
>>>> Signed-off-by: Michal Wajdeczko <[email protected]>
>>>> ---
>>>> v2: new macro names due to conflict with crypto/aria.h
>>>> explicit cast and truncation everywhere (Alexey)
>>>> moved to wordpart.h (Andy)
>>>> ---
>>>> Cc: Kees Cook <[email protected]>
>>>> Cc: Andy Shevchenko <[email protected]>
>>>> Cc: Alexey Dobriyan <[email protected]>
>>>> Cc: Jani Nikula <[email protected]>
>>>> ---
>>>> include/linux/wordpart.h | 32 ++++++++++++++++++++++++++++++++
>>>> 1 file changed, 32 insertions(+)
>>>>
>>>> diff --git a/include/linux/wordpart.h b/include/linux/wordpart.h
>>>> index f6f8f83b15b0..8c75a5355112 100644
>>>> --- a/include/linux/wordpart.h
>>>> +++ b/include/linux/wordpart.h
>>>> @@ -31,6 +31,38 @@
>>>> */
>>>> #define lower_16_bits(n) ((u16)((n) & 0xffff))
>>>>
>>>> +/**
>>>> + * make_u16_from_u8 - make u16 value from two u8 values
>>>> + * @hi: value representing upper 8 bits
>>>> + * @lo: value representing lower 8 bits
>>>> + */
>>>> +#define make_u16_from_u8(hi, lo) ((u16)((u16)(u8)(hi) << 8 | (u8)(lo)))
>>>
>>> Do we want to actually do type validation here? Right now it's just
>>> cast/truncating, which based on the version log is by design. Is silent
>>> truncation the right thing to do?
>>
>> note that even FIELD_PREP() is doing silent truncation and these macros
>> here could be treated as specialized/simplified variants of FIELD_PREP()
>> as alternate implementation can look like:
>
> Also, isn't all of this endian-specific?

endianness shouldn't matter here

so I guess the only question now is whether we want to have simple
direct macros like lower|upper_bits() or go with macros build on top of
the FIELD_PREP_CONST() or drop the idea completely and force the drivers
to invent the wheel on its own

2024-04-08 13:28:50

by Jani Nikula

[permalink] [raw]
Subject: Re: [PATCH 1/2] wordpart.h: Helpers for making u16/u32/u64 values

On Tue, 26 Mar 2024, Michal Wajdeczko <[email protected]> wrote:
> On 15.02.2024 23:47, Kees Cook wrote:
>> On Thu, Feb 15, 2024 at 09:40:40PM +0100, Michal Wajdeczko wrote:
>>> On 14.02.2024 23:09, Kees Cook wrote:
>>>> On Wed, Feb 14, 2024 at 10:46:53PM +0100, Michal Wajdeczko wrote:
>>>>> It is quite common practice to make u16, u32 or u64 values from
>>>>> smaller words. Add simple helpers for that.
>>>>>
>>>>> Signed-off-by: Michal Wajdeczko <[email protected]>
>>>>> ---
>>>>> v2: new macro names due to conflict with crypto/aria.h
>>>>> explicit cast and truncation everywhere (Alexey)
>>>>> moved to wordpart.h (Andy)
>>>>> ---
>>>>> Cc: Kees Cook <[email protected]>
>>>>> Cc: Andy Shevchenko <[email protected]>
>>>>> Cc: Alexey Dobriyan <[email protected]>
>>>>> Cc: Jani Nikula <[email protected]>
>>>>> ---
>>>>> include/linux/wordpart.h | 32 ++++++++++++++++++++++++++++++++
>>>>> 1 file changed, 32 insertions(+)
>>>>>
>>>>> diff --git a/include/linux/wordpart.h b/include/linux/wordpart.h
>>>>> index f6f8f83b15b0..8c75a5355112 100644
>>>>> --- a/include/linux/wordpart.h
>>>>> +++ b/include/linux/wordpart.h
>>>>> @@ -31,6 +31,38 @@
>>>>> */
>>>>> #define lower_16_bits(n) ((u16)((n) & 0xffff))
>>>>>
>>>>> +/**
>>>>> + * make_u16_from_u8 - make u16 value from two u8 values
>>>>> + * @hi: value representing upper 8 bits
>>>>> + * @lo: value representing lower 8 bits
>>>>> + */
>>>>> +#define make_u16_from_u8(hi, lo) ((u16)((u16)(u8)(hi) << 8 | (u8)(lo)))
>>>>
>>>> Do we want to actually do type validation here? Right now it's just
>>>> cast/truncating, which based on the version log is by design. Is silent
>>>> truncation the right thing to do?

Doesn't the name imply strongly enough that we're only interested in the
N bits from each parameter? I think not truncating makes these harder to
use (if it means e.g. casting on the caller side).

>>>
>>> note that even FIELD_PREP() is doing silent truncation and these macros
>>> here could be treated as specialized/simplified variants of FIELD_PREP()
>>> as alternate implementation can look like:
>>
>> Also, isn't all of this endian-specific?

None of this assumes endianness.

> endianness shouldn't matter here
>
> so I guess the only question now is whether we want to have simple
> direct macros like lower|upper_bits() or go with macros build on top of
> the FIELD_PREP_CONST() or drop the idea completely and force the drivers
> to invent the wheel on its own

Yeah, please let's do this so we don't have to keep adding them to
drivers.

BR,
Jani.


--
Jani Nikula, Intel