Rust for Linux List
 help / color / mirror / Atom feed
* [PATCH v3 0/2] pwm: th1520: Fix 32-bit build with COMPILE_TEST
@ 2026-10-30  2:02 FUJITA Tomonori
  2026-10-30  2:02 ` [PATCH v3 1/2] rust: math: add div64_u64() and div64_u64_round_up() FUJITA Tomonori
  2026-10-30  2:02 ` [PATCH v3 2/2] pwm: th1520: Fix 32-bit build with COMPILE_TEST FUJITA Tomonori
  0 siblings, 2 replies; 3+ messages in thread
From: FUJITA Tomonori @ 2026-10-30  2:02 UTC (permalink / raw)
  To: fustini, guoren, ojeda, ukleinek, wefu
  Cc: a.hindborg, acourbot, aliceryhl, bjorn3_gh, boqun,
	chenhan0017.work, dakr, daniel.almeida, gary, linux-riscv, lossin,
	m.wilczynski, tamird, tmgross, work, linux-pwm, rust-for-linux,
	FUJITA Tomonori

From: FUJITA Tomonori <fujita.tomonori@gmail.com>

This series fixes the 32-bit build of the TH1520 PWM driver with
COMPILE_TEST. v2 limited COMPILE_TEST to 64BIT. Uwe asked to use the
div helpers instead, so v3 does that.

Patch 1 adds a math module to the kernel crate with Rust versions of
div64_u64() and DIV64_U64_ROUND_UP(). Patch 2 uses them in the driver.

The driver only needs u64 by u64 division. It does not need a 128-bit
intermediate value like mul_u64_u64_div_u64().

Uwe, are you OK with this series going through the Rust tree?

chenhan's series [1] also adds rust/kernel/math.rs, with signed
division helpers. Both series use the same module header, so whichever
is applied later needs only a small rebase.

Tested with the doctests on x86_64 and 32-bit ARM QEMU.

[1] https://lore.kernel.org/rust-for-linux/20261023130413.178487-1-chenhan0017.work@gmail.com/

v3:
- Use div helpers instead of limiting COMPILE_TEST to 64BIT (Uwe)
- Add a math module with div64_u64() and div64_u64_round_up()
- Drop Cc: stable and the Reviewed-by tags, since the change is different
v2: https://lore.kernel.org/rust-for-linux/20260930101257.1649945-1-tomo@flapping.org/
- Fix a typo in the commit message
- Add Cc: stable, Reported-by and Closes tags
- Add Reviewed-by tags from Andreas and Gary
- Rebase on v7.3-rc5
v1: https://lore.kernel.org/all/20260929095612.1072417-1-tomo@flapping.org/

FUJITA Tomonori (2):
  rust: math: add div64_u64() and div64_u64_round_up()
  pwm: th1520: Fix 32-bit build with COMPILE_TEST

 drivers/pwm/pwm_th1520.rs |  8 +++--
 rust/kernel/lib.rs        |  1 +
 rust/kernel/math.rs       | 71 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 78 insertions(+), 2 deletions(-)
 create mode 100644 rust/kernel/math.rs


base-commit: c339f4010dea8b0d754f84ace70cd1b089878ef8
-- 
2.43.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH v3 1/2] rust: math: add div64_u64() and div64_u64_round_up()
  2026-10-30  2:02 [PATCH v3 0/2] pwm: th1520: Fix 32-bit build with COMPILE_TEST FUJITA Tomonori
@ 2026-10-30  2:02 ` FUJITA Tomonori
  2026-10-30  2:02 ` [PATCH v3 2/2] pwm: th1520: Fix 32-bit build with COMPILE_TEST FUJITA Tomonori
  1 sibling, 0 replies; 3+ messages in thread
From: FUJITA Tomonori @ 2026-10-30  2:02 UTC (permalink / raw)
  To: fustini, guoren, ojeda, ukleinek, wefu
  Cc: a.hindborg, acourbot, aliceryhl, bjorn3_gh, boqun,
	chenhan0017.work, dakr, daniel.almeida, gary, linux-riscv, lossin,
	m.wilczynski, tamird, tmgross, work, linux-pwm, rust-for-linux,
	FUJITA Tomonori

From: FUJITA Tomonori <fujita.tomonori@gmail.com>

On 32-bit architectures, dividing a u64 by a u64 with the `/` operator
makes the compiler emit a call to a compiler runtime function, such as
__aeabi_uldivmod() on arm. The kernel does not provide these functions,
so the build fails when Rust code that is also built for 32-bit
architectures uses `/` on u64.

C code uses the helpers in include/linux/math64.h instead. Add a math
module with Rust versions of two of them:

- div64_u64(), the same as div64_u64() in C.
- div64_u64_round_up(), the same as DIV64_U64_ROUND_UP() in C.

On 64-bit architectures, both use `/`. On 32-bit architectures,
div64_u64() calls the C function. Both panic if the divisor is zero,
as `/` does.

Assisted-by: LLM
Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
---
 rust/kernel/lib.rs  |  1 +
 rust/kernel/math.rs | 71 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 72 insertions(+)
 create mode 100644 rust/kernel/math.rs

diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index 1ab41129d557..482fef8be2e8 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -100,6 +100,7 @@
 pub mod kunit;
 pub mod list;
 pub mod maple_tree;
+pub mod math;
 pub mod mem;
 pub mod miscdevice;
 pub mod mm;
diff --git a/rust/kernel/math.rs b/rust/kernel/math.rs
new file mode 100644
index 000000000000..395816639af8
--- /dev/null
+++ b/rust/kernel/math.rs
@@ -0,0 +1,71 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Integer arithmetic helpers.
+//!
+//! C header: [`include/linux/math64.h`](srctree/include/linux/math64.h).
+
+/// Divides a [`u64`] dividend by a [`u64`] divisor, rounding down.
+///
+/// On 32-bit architectures, `/` on [`u64`] needs a function that the kernel does
+/// not provide. Use this function in code that is also built for 32-bit
+/// architectures.
+///
+/// # Panics
+///
+/// Panics if `divisor` is zero.
+///
+/// # Examples
+///
+/// ```
+/// use kernel::math::div64_u64;
+///
+/// assert_eq!(div64_u64(7, 2), 3);
+/// assert_eq!(div64_u64(u64::MAX, 1 << 32), u64::from(u32::MAX));
+/// ```
+#[inline]
+pub fn div64_u64(dividend: u64, divisor: u64) -> u64 {
+    if divisor == 0 {
+        panic!("attempt to divide by zero");
+    }
+
+    #[cfg(CONFIG_64BIT)]
+    {
+        dividend / divisor
+    }
+
+    #[cfg(not(CONFIG_64BIT))]
+    {
+        // SAFETY: `div64_u64()` requires a non-zero `divisor`, which is
+        // checked above.
+        unsafe { bindings::div64_u64(dividend, divisor) }
+    }
+}
+
+/// Divides a [`u64`] dividend by a [`u64`] divisor, rounding up.
+///
+/// # Panics
+///
+/// Panics if `divisor` is zero.
+///
+/// # Examples
+///
+/// ```
+/// use kernel::math::div64_u64_round_up;
+///
+/// assert_eq!(div64_u64_round_up(7, 2), 4);
+/// assert_eq!(div64_u64_round_up(6, 2), 3);
+/// assert_eq!(div64_u64_round_up(u64::MAX, 2), 1 << 63);
+/// ```
+#[inline]
+pub fn div64_u64_round_up(dividend: u64, divisor: u64) -> u64 {
+    let quotient = div64_u64(dividend, divisor);
+
+    // `quotient * divisor` is not greater than `dividend`, so this does not
+    // overflow.
+    if dividend - quotient * divisor == 0 {
+        quotient
+    } else {
+        // A non-zero remainder means `divisor >= 2`, so this does not overflow.
+        quotient + 1
+    }
+}
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH v3 2/2] pwm: th1520: Fix 32-bit build with COMPILE_TEST
  2026-10-30  2:02 [PATCH v3 0/2] pwm: th1520: Fix 32-bit build with COMPILE_TEST FUJITA Tomonori
  2026-10-30  2:02 ` [PATCH v3 1/2] rust: math: add div64_u64() and div64_u64_round_up() FUJITA Tomonori
@ 2026-10-30  2:02 ` FUJITA Tomonori
  1 sibling, 0 replies; 3+ messages in thread
From: FUJITA Tomonori @ 2026-10-30  2:02 UTC (permalink / raw)
  To: fustini, guoren, ojeda, ukleinek, wefu
  Cc: a.hindborg, acourbot, aliceryhl, bjorn3_gh, boqun,
	chenhan0017.work, dakr, daniel.almeida, gary, linux-riscv, lossin,
	m.wilczynski, tamird, tmgross, work, linux-pwm, rust-for-linux,
	FUJITA Tomonori

From: FUJITA Tomonori <fujita.tomonori@gmail.com>

Fix the following build error on 32-bit ARM with COMPILE_TEST:

  ERROR: modpost: drivers/pwm/pwm_th1520.ko: symbol '__aeabi_uldivmod' undefined!

The driver divides u64 values when it converts between nanoseconds and
clock cycles. On 32-bit ARM, these divisions are compiled to calls to
__aeabi_uldivmod, which the kernel does not provide.

Use div64_u64() and div64_u64_round_up() for these divisions, in the
same way as C drivers use div64_u64() and DIV64_U64_ROUND_UP(). The
results do not change.

Fixes: 3c180003dffb ("pwm: th1520: Fix missing Kconfig dependencies")
Reported-by: Andreas Hindborg <a.hindborg@kernel.org>
Closes: https://rust-for-linux.zulipchat.com/#narrow/channel/291565-Help/topic/64bit.20division.20in.20.60pwm_th1520.2Ers.60/near/626825599
Suggested-by: Uwe Kleine-König <ukleinek@kernel.org>
Assisted-by: LLM
Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
---
 drivers/pwm/pwm_th1520.rs | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/pwm/pwm_th1520.rs b/drivers/pwm/pwm_th1520.rs
index 728993998446..bd05fe49650e 100644
--- a/drivers/pwm/pwm_th1520.rs
+++ b/drivers/pwm/pwm_th1520.rs
@@ -31,6 +31,10 @@
         mem::DevresIoMem,
         Io, //
     },
+    math::{
+        div64_u64,
+        div64_u64_round_up, //
+    },
     of,
     platform,
     prelude::*,
@@ -68,13 +72,13 @@ const fn th1520_pwm_fp(n: u32) -> usize {
 fn ns_to_cycles(ns: u64, rate_hz: u64) -> u64 {
     const NSEC_PER_SEC_U64: u64 = time::NSEC_PER_SEC as u64;
 
-    ns.saturating_mul(rate_hz) / NSEC_PER_SEC_U64
+    div64_u64(ns.saturating_mul(rate_hz), NSEC_PER_SEC_U64)
 }
 
 fn cycles_to_ns(cycles: u32, rate_hz: u64) -> u64 {
     const NSEC_PER_SEC_U64: u64 = time::NSEC_PER_SEC as u64;
 
-    (u64::from(cycles) * NSEC_PER_SEC_U64).div_ceil(rate_hz)
+    div64_u64_round_up(u64::from(cycles) * NSEC_PER_SEC_U64, rate_hz)
 }
 
 /// Hardware-specific waveform representation for TH1520.
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-10-30  2:02 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-30  2:02 [PATCH v3 0/2] pwm: th1520: Fix 32-bit build with COMPILE_TEST FUJITA Tomonori
2026-10-30  2:02 ` [PATCH v3 1/2] rust: math: add div64_u64() and div64_u64_round_up() FUJITA Tomonori
2026-10-30  2:02 ` [PATCH v3 2/2] pwm: th1520: Fix 32-bit build with COMPILE_TEST FUJITA Tomonori

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox