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(-)
---
base-commit: 44f0dcf476140c1077ee3dbe16a80fdb6f8265c4
change-id: 20260730-math64-resync-3e50332c1683

Best regards,
--  
Alexey Charkov <[email protected]>

Reply via email to