On Thu, Jul 30, 2026 at 10:41 PM Alexey Charkov <[email protected]> wrote:
>
> U-Boot's <linux/math64.h> was last really synced with Linux in 2017 by
> commit 0342e335ba88 ("lib: div64: sync with Linux"). Since then it has
> only been patched locally twice, and both times in ways that increased
> the divergence rather than tracking upstream.
>
> The one that prompted this series is DIV64_U64_ROUND_UP(). Commit
> 3adc17f60bf8 ("lib: div64: Add support for round up of div64_u64") added
> it inside the #if BITS_PER_LONG == 64 branch, whereas upstream defines
> it unconditionally after that block, so any 32-bit user fails to build.
>
> While auditing the header, two bugs turned up in lib/div64.c, so this
> series starts with those. Both are 32-bit only:
>
> - div64_u64() and div64_u64_rem() shifted by 1 + fls(high) instead of
>   fls(high), losing a bit of the divisor. Linux fixed this in 2019, while
>   U-Boot never picked it up.
>
> - div64_s64() used abs() on s64 operands. U-Boot's abs() is not 64-bit
>   safe: its own comment says to use abs64() instead. Both operands were
>   silently truncated to 32 bits.
>
> Transitive headers that affect what <linux/math64.h> offers were checked
> too. <linux/math.h> and <vdso/math64.h> have no U-Boot equivalent and
> are not needed; do_div() comes from U-Boot's <div64.h> in place of
> <asm/div64.h>.
>
> Deliberately left out of this resync:
>
> - CONFIG_ARCH_SUPPORTS_INT128 is tested by <linux/math64.h> but isn't
>   defined anywhere in U-Boot, so the __int128 fast paths for
>   mul_u64_u32_shr() and mul_u64_u64_shr() are dead code on arm64,
>   riscv64 and x86_64 where they could have been useful. Wiring it up in
>   the arch Kconfigs looks like an easy win (but could result in subtle
>   behavior changes or code size drift, so needs to be approached
>   separately).
>
> - abs() in <linux/kernel.h> diverges from Linux and is not 64-bit safe.
>   Patch 2 and patch 5 work around it with abs64() at the two call
>   sites that need it. Replacing it with Linux's __abs_choose_expr()
>   version would be the root fix, but changes abs()'s return type from
>   long to typeof(x) for every caller in the tree.
>
> - abs_diff() lives in <linux/math64.h> here rather than upstream's
>   <linux/math.h>; it could move to <linux/kernel.h> alongside abs().
>
> - mul_u64_add_u64_div_u64() and the mul_u64_u64_div_u64() macros are
>   not ported, as they need a u128 type and ~110 lines of
>   lib/math/div64.c that nothing in U-Boot calls yet.
>
> Build tested with both gcc and clang for evb-rk3288-rk808 (32-bit LE),
> generic-rk3576 (64-bit LE), malta (32-bit big-endian, which is what
> actually compiles the __BIG_ENDIAN union paths), plus sandbox and
> tools-only. No size change on any phase.
>
> Signed-off-by: Alexey Charkov <[email protected]>
> ---
> Alexey Charkov (5):
>       lib: div64: fix off-by-one shift in div64_u64() and div64_u64_rem()
>       lib: div64: use abs64() for the 64-bit operands of div64_s64()
>       lib: div64: inline __iter_div_u64_rem() into its only user
>       lib: div64: sync with Linux v7.1
>       lib: math64: sync <linux/math64.h> with Linux v7.1
>
>  include/linux/math64.h | 201 
> +++++++++++++++++++++++++++++++++++++++++--------
>  lib/div64.c            |  46 +++++++----
>  2 files changed, 203 insertions(+), 44 deletions(-)

NB: CI passes all green:

https://git.u-boot-project.org/u-boot/contributors/alchark/u-boot/-/pipelines/812

Best regards,
Alexey

Reply via email to