* [PATCH] rust: bitops: add helpers for _find_* functions
@ 2025-12-03 15:42 Alice Ryhl
2025-12-03 22:35 ` Andreas Hindborg
0 siblings, 1 reply; 3+ messages in thread
From: Alice Ryhl @ 2025-12-03 15:42 UTC (permalink / raw)
To: Yury Norov, Burak Emir
Cc: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Trevor Gross, Danilo Krummrich,
rust-for-linux, linux-kernel, Alice Ryhl
On 32-bit ARM, _find_next_bit does not exist because ARM provides that
function through a #define instead. This means that Rust, which calls
the underscored version, fails to find it. This triggers errors:
ld.lld: error: undefined symbol: _find_next_bit
>>> referenced by bitmap.rs:459 (rust/kernel/bitmap.rs:459)
>>> rust/kernel.o:(kernel::bitmap::tests::kunit_rust_wrapper_bitmap_borrow) in archive vmlinux.a
>>> referenced by bitmap.rs:459 (rust/kernel/bitmap.rs:459)
>>> rust/kernel.o:(kernel::bitmap::tests::kunit_rust_wrapper_bitmap_set_clear_find) in archive vmlinux.a
>>> referenced by bitmap.rs:459 (rust/kernel/bitmap.rs:459)
>>> rust/kernel.o:(kernel::bitmap::tests::kunit_rust_wrapper_bitmap_set_clear_find) in archive vmlinux.a
>>> referenced 10 more times
ld.lld: error: undefined symbol: _find_next_zero_bit
>>> referenced by bitmap.rs:479 (rust/kernel/bitmap.rs:479)
>>> rust/kernel.o:(kernel::bitmap::tests::kunit_rust_wrapper_bitmap_copy) in archive vmlinux.a
>>> referenced by bitmap.rs:479 (rust/kernel/bitmap.rs:479)
>>> rust/kernel.o:(kernel::bitmap::tests::kunit_rust_wrapper_bitmap_set_clear_find) in archive vmlinux.a
>>> referenced by bitmap.rs:479 (rust/kernel/bitmap.rs:479)
>>> rust/kernel.o:(kernel::bitmap::tests::kunit_rust_wrapper_owned_bitmap_out_of_bounds) in archive vmlinux.a
>>> referenced 6 more times
To fix this, add Rust helpers in this particular case.
Fixes: 6cf93a9ed39e ("rust: add bindings for bitops.h")
Reported-by: Andreas Hindborg <a.hindborg@kernel.org>
Closes: https://rust-for-linux.zulipchat.com/#narrow/channel/x/topic/x/near/561677301
Tested-by: Andreas Hindborg <a.hindborg@kernel.org>
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
---
rust/helpers/bitops.c | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/rust/helpers/bitops.c b/rust/helpers/bitops.c
index 5d0861d29d3f0d705a014ae4601685828405f33b..84061af591a261f7268ffe6535282bf3c7608e2d 100644
--- a/rust/helpers/bitops.c
+++ b/rust/helpers/bitops.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/bitops.h>
+#include <linux/find.h>
void rust_helper___set_bit(unsigned long nr, unsigned long *addr)
{
@@ -21,3 +22,34 @@ void rust_helper_clear_bit(unsigned long nr, volatile unsigned long *addr)
{
clear_bit(nr, addr);
}
+
+/*
+ * Rust normally calls the single-underscore-prefixed version of these
+ * functions, which are not inlined. However, on some platforms, they do not
+ * exist. In those cases, provide a rust helper for the underscored version.
+ */
+#ifdef find_next_zero_bit
+__rust_helper unsigned long
+rust_helper__find_next_zero_bit(const unsigned long *addr, unsigned long size,
+ unsigned long offset)
+{
+ return find_next_zero_bit(addr, size, offset);
+}
+#endif /* find_next_zero_bit */
+
+#ifdef find_next_bit
+__rust_helper unsigned long
+rust_helper__find_next_bit(const unsigned long *addr, unsigned long size,
+ unsigned long offset)
+{
+ return find_next_bit(addr, size, offset);
+}
+#endif /* find_next_bit */
+
+#ifdef find_last_bit
+__rust_helper unsigned long
+rust_helper__find_last_bit(const unsigned long *addr, unsigned long size)
+{
+ return find_last_bit(addr, size);
+}
+#endif /* find_last_bit */
---
base-commit: 54e3eae855629702c566bd2e130d9f40e7f35bde
change-id: 20251203-bitops-find-helper-25ed1bbae700
Best regards,
--
Alice Ryhl <aliceryhl@google.com>
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: [PATCH] rust: bitops: add helpers for _find_* functions 2025-12-03 15:42 [PATCH] rust: bitops: add helpers for _find_* functions Alice Ryhl @ 2025-12-03 22:35 ` Andreas Hindborg 2025-12-04 9:04 ` Alice Ryhl 0 siblings, 1 reply; 3+ messages in thread From: Andreas Hindborg @ 2025-12-03 22:35 UTC (permalink / raw) To: Alice Ryhl, Yury Norov, Burak Emir Cc: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Trevor Gross, Danilo Krummrich, rust-for-linux, linux-kernel, Alice Ryhl Alice Ryhl <aliceryhl@google.com> writes: > On 32-bit ARM, _find_next_bit does not exist because ARM provides that > function through a #define instead. This means that Rust, which calls > the underscored version, fails to find it. This triggers errors: > > ld.lld: error: undefined symbol: _find_next_bit > >>> referenced by bitmap.rs:459 (rust/kernel/bitmap.rs:459) > >>> rust/kernel.o:(kernel::bitmap::tests::kunit_rust_wrapper_bitmap_borrow) in archive vmlinux.a > >>> referenced by bitmap.rs:459 (rust/kernel/bitmap.rs:459) > >>> rust/kernel.o:(kernel::bitmap::tests::kunit_rust_wrapper_bitmap_set_clear_find) in archive vmlinux.a > >>> referenced by bitmap.rs:459 (rust/kernel/bitmap.rs:459) > >>> rust/kernel.o:(kernel::bitmap::tests::kunit_rust_wrapper_bitmap_set_clear_find) in archive vmlinux.a > >>> referenced 10 more times > > ld.lld: error: undefined symbol: _find_next_zero_bit > >>> referenced by bitmap.rs:479 (rust/kernel/bitmap.rs:479) > >>> rust/kernel.o:(kernel::bitmap::tests::kunit_rust_wrapper_bitmap_copy) in archive vmlinux.a > >>> referenced by bitmap.rs:479 (rust/kernel/bitmap.rs:479) > >>> rust/kernel.o:(kernel::bitmap::tests::kunit_rust_wrapper_bitmap_set_clear_find) in archive vmlinux.a > >>> referenced by bitmap.rs:479 (rust/kernel/bitmap.rs:479) > >>> rust/kernel.o:(kernel::bitmap::tests::kunit_rust_wrapper_owned_bitmap_out_of_bounds) in archive vmlinux.a > >>> referenced 6 more times > > To fix this, add Rust helpers in this particular case. > > Fixes: 6cf93a9ed39e ("rust: add bindings for bitops.h") > Reported-by: Andreas Hindborg <a.hindborg@kernel.org> > Closes: https://rust-for-linux.zulipchat.com/#narrow/channel/x/topic/x/near/561677301 > Tested-by: Andreas Hindborg <a.hindborg@kernel.org> > Signed-off-by: Alice Ryhl <aliceryhl@google.com> > --- > rust/helpers/bitops.c | 32 ++++++++++++++++++++++++++++++++ > 1 file changed, 32 insertions(+) > > diff --git a/rust/helpers/bitops.c b/rust/helpers/bitops.c > index 5d0861d29d3f0d705a014ae4601685828405f33b..84061af591a261f7268ffe6535282bf3c7608e2d 100644 > --- a/rust/helpers/bitops.c > +++ b/rust/helpers/bitops.c > @@ -1,6 +1,7 @@ > // SPDX-License-Identifier: GPL-2.0 > > #include <linux/bitops.h> > +#include <linux/find.h> > > void rust_helper___set_bit(unsigned long nr, unsigned long *addr) > { > @@ -21,3 +22,34 @@ void rust_helper_clear_bit(unsigned long nr, volatile unsigned long *addr) > { > clear_bit(nr, addr); > } > + > +/* > + * Rust normally calls the single-underscore-prefixed version of these > + * functions, which are not inlined. However, on some platforms, they do not > + * exist. In those cases, provide a rust helper for the underscored version. > + */ > +#ifdef find_next_zero_bit > +__rust_helper unsigned long > +rust_helper__find_next_zero_bit(const unsigned long *addr, unsigned long size, > + unsigned long offset) > +{ > + return find_next_zero_bit(addr, size, offset); > +} > +#endif /* find_next_zero_bit */ > + > +#ifdef find_next_bit > +__rust_helper unsigned long > +rust_helper__find_next_bit(const unsigned long *addr, unsigned long size, > + unsigned long offset) > +{ > + return find_next_bit(addr, size, offset); > +} > +#endif /* find_next_bit */ > + > +#ifdef find_last_bit > +__rust_helper unsigned long > +rust_helper__find_last_bit(const unsigned long *addr, unsigned long size) > +{ > + return find_last_bit(addr, size); > +} > +#endif /* find_last_bit */ > > --- > base-commit: 54e3eae855629702c566bd2e130d9f40e7f35bde > change-id: 20251203-bitops-find-helper-25ed1bbae700 > > Best regards, > -- > Alice Ryhl <aliceryhl@google.com> I messed up when testing this patch. It actually does not solve the issue. It appears that bindgen will emit an extern "C" declaration for the missing C functions, even though they are not in the symbol table. When we add the rust helpers, the declarations emitted based on the non-existent C functions will mask the rust helper functions. We can circumvent this by using another name for our helper. While it works, it is not fixing the root cause. I am not sure why bindgen emits these functions even though they are not in the symbol table at the end. At any rate, the following is a workaround: diff --git a/rust/helpers/bitops.c b/rust/helpers/bitops.c index 5d0861d29d3f0..4f15315bc47f2 100644 --- a/rust/helpers/bitops.c +++ b/rust/helpers/bitops.c @@ -21,3 +21,26 @@ void rust_helper_clear_bit(unsigned long nr, volatile unsigned long *addr) { clear_bit(nr, addr); } + +/* + * Rust normally calls the single-underscore-prefixed version of these + * functions, which are not inlined. However, on some platforms, they do not + * exist. In those cases, provide a rust helper for the underscored version. + */ +#ifdef find_next_zero_bit +__rust_helper unsigned long +rust_helper_r_find_next_zero_bit(const unsigned long *addr, unsigned long size, + unsigned long offset) +{ + return find_next_zero_bit(addr, size, offset); +} +#endif /* find_next_zero_bit */ + +#ifdef find_next_bit +__rust_helper unsigned long +rust_helper_r_find_next_bit(const unsigned long *addr, unsigned long size, + unsigned long offset) +{ + return find_next_bit(addr, size, offset); +} +#endif /* find_next_bit */ diff --git a/rust/kernel/bitmap.rs b/rust/kernel/bitmap.rs index aa8fc7bf06fc9..88af73edb0c21 100644 --- a/rust/kernel/bitmap.rs +++ b/rust/kernel/bitmap.rs @@ -456,7 +456,7 @@ pub fn next_bit(&self, start: usize) -> Option<usize> { ); // SAFETY: `_find_next_bit` tolerates out-of-bounds arguments and returns a // value larger than or equal to `self.len()` in that case. - let index = unsafe { bindings::_find_next_bit(self.as_ptr(), self.len(), start) }; + let index = unsafe { bindings::r_find_next_bit(self.as_ptr(), self.len(), start) }; if index >= self.len() { None } else { @@ -476,7 +476,7 @@ pub fn next_zero_bit(&self, start: usize) -> Option<usize> { ); // SAFETY: `_find_next_zero_bit` tolerates out-of-bounds arguments and returns a // value larger than or equal to `self.len()` in that case. - let index = unsafe { bindings::_find_next_zero_bit(self.as_ptr(), self.len(), start) }; + let index = unsafe { bindings::r_find_next_zero_bit(self.as_ptr(), self.len(), start) }; if index >= self.len() { None } else { Best regards, Andreas Hindborg ^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] rust: bitops: add helpers for _find_* functions 2025-12-03 22:35 ` Andreas Hindborg @ 2025-12-04 9:04 ` Alice Ryhl 0 siblings, 0 replies; 3+ messages in thread From: Alice Ryhl @ 2025-12-04 9:04 UTC (permalink / raw) To: Andreas Hindborg Cc: Yury Norov, Burak Emir, Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin, Trevor Gross, Danilo Krummrich, rust-for-linux, linux-kernel On Wed, Dec 03, 2025 at 11:35:54PM +0100, Andreas Hindborg wrote: > Alice Ryhl <aliceryhl@google.com> writes: > > > On 32-bit ARM, _find_next_bit does not exist because ARM provides that > > function through a #define instead. This means that Rust, which calls > > the underscored version, fails to find it. This triggers errors: > > > > ld.lld: error: undefined symbol: _find_next_bit > > >>> referenced by bitmap.rs:459 (rust/kernel/bitmap.rs:459) > > >>> rust/kernel.o:(kernel::bitmap::tests::kunit_rust_wrapper_bitmap_borrow) in archive vmlinux.a > > >>> referenced by bitmap.rs:459 (rust/kernel/bitmap.rs:459) > > >>> rust/kernel.o:(kernel::bitmap::tests::kunit_rust_wrapper_bitmap_set_clear_find) in archive vmlinux.a > > >>> referenced by bitmap.rs:459 (rust/kernel/bitmap.rs:459) > > >>> rust/kernel.o:(kernel::bitmap::tests::kunit_rust_wrapper_bitmap_set_clear_find) in archive vmlinux.a > > >>> referenced 10 more times > > > > ld.lld: error: undefined symbol: _find_next_zero_bit > > >>> referenced by bitmap.rs:479 (rust/kernel/bitmap.rs:479) > > >>> rust/kernel.o:(kernel::bitmap::tests::kunit_rust_wrapper_bitmap_copy) in archive vmlinux.a > > >>> referenced by bitmap.rs:479 (rust/kernel/bitmap.rs:479) > > >>> rust/kernel.o:(kernel::bitmap::tests::kunit_rust_wrapper_bitmap_set_clear_find) in archive vmlinux.a > > >>> referenced by bitmap.rs:479 (rust/kernel/bitmap.rs:479) > > >>> rust/kernel.o:(kernel::bitmap::tests::kunit_rust_wrapper_owned_bitmap_out_of_bounds) in archive vmlinux.a > > >>> referenced 6 more times > > > > To fix this, add Rust helpers in this particular case. > > > > Fixes: 6cf93a9ed39e ("rust: add bindings for bitops.h") > > Reported-by: Andreas Hindborg <a.hindborg@kernel.org> > > Closes: https://rust-for-linux.zulipchat.com/#narrow/channel/x/topic/x/near/561677301 > > Tested-by: Andreas Hindborg <a.hindborg@kernel.org> > > Signed-off-by: Alice Ryhl <aliceryhl@google.com> > > --- > > rust/helpers/bitops.c | 32 ++++++++++++++++++++++++++++++++ > > 1 file changed, 32 insertions(+) > > > > diff --git a/rust/helpers/bitops.c b/rust/helpers/bitops.c > > index 5d0861d29d3f0d705a014ae4601685828405f33b..84061af591a261f7268ffe6535282bf3c7608e2d 100644 > > --- a/rust/helpers/bitops.c > > +++ b/rust/helpers/bitops.c > > @@ -1,6 +1,7 @@ > > // SPDX-License-Identifier: GPL-2.0 > > > > #include <linux/bitops.h> > > +#include <linux/find.h> > > > > void rust_helper___set_bit(unsigned long nr, unsigned long *addr) > > { > > @@ -21,3 +22,34 @@ void rust_helper_clear_bit(unsigned long nr, volatile unsigned long *addr) > > { > > clear_bit(nr, addr); > > } > > + > > +/* > > + * Rust normally calls the single-underscore-prefixed version of these > > + * functions, which are not inlined. However, on some platforms, they do not > > + * exist. In those cases, provide a rust helper for the underscored version. > > + */ > > +#ifdef find_next_zero_bit > > +__rust_helper unsigned long > > +rust_helper__find_next_zero_bit(const unsigned long *addr, unsigned long size, > > + unsigned long offset) > > +{ > > + return find_next_zero_bit(addr, size, offset); > > +} > > +#endif /* find_next_zero_bit */ > > + > > +#ifdef find_next_bit > > +__rust_helper unsigned long > > +rust_helper__find_next_bit(const unsigned long *addr, unsigned long size, > > + unsigned long offset) > > +{ > > + return find_next_bit(addr, size, offset); > > +} > > +#endif /* find_next_bit */ > > + > > +#ifdef find_last_bit > > +__rust_helper unsigned long > > +rust_helper__find_last_bit(const unsigned long *addr, unsigned long size) > > +{ > > + return find_last_bit(addr, size); > > +} > > +#endif /* find_last_bit */ > > > > --- > > base-commit: 54e3eae855629702c566bd2e130d9f40e7f35bde > > change-id: 20251203-bitops-find-helper-25ed1bbae700 > > > > Best regards, > > -- > > Alice Ryhl <aliceryhl@google.com> > > I messed up when testing this patch. It actually does not solve the > issue. > > It appears that bindgen will emit an extern "C" declaration for the > missing C functions, even though they are not in the symbol table. When > we add the rust helpers, the declarations emitted based on the > non-existent C functions will mask the rust helper functions. Yeah, when Rust sees both a helper and real function, we configured it to pick the real one. > We can circumvent this by using another name for our helper. While it > works, it is not fixing the root cause. I am not sure why bindgen emits > these functions even though they are not in the symbol table at the end. I think a much better workaround is to adjust the header file: #ifndef find_next_zero_bit unsigned long _find_next_zero_bit(const unsigned long *addr, unsigned long nbits, unsigned long start); #endif Alice ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-12-04 9:04 UTC | newest] Thread overview: 3+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-12-03 15:42 [PATCH] rust: bitops: add helpers for _find_* functions Alice Ryhl 2025-12-03 22:35 ` Andreas Hindborg 2025-12-04 9:04 ` Alice Ryhl
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).