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
