Enable experimental rust support for ppc64le and ppc32be. The patch for ppc32 has been provided by Link Mauve[1] and ppc64le support[2] has been merged over it. ppc32 needs some toolchain fixes mentioned in the patch `rust: Add PowerPC support` and the discussion for that is done here[1].
This has been tested on - powernv9 hardware - pseries P11 hardware - pseries(9, 10) qemu - powernv(9, 10) qemu - rustdoc on x86 and powerpc64le - rusttest on x86 and powerpc64le
We are actively working with our LLVM team to get the target for ppc, ppc64 and ppc64le in the rust compiler.
[1] https://lore.kernel.org/all/20260204030507.8203-1-linkmauve@linkmauve.fr [2] https://lore.kernel.org/all/20260204042417.83903-1-mkchauras@gmail.com
Changelog: V12 -> V13: - Added a patch for fixing build issue on ppc32 by Link Mauve - Added another patch to fix a build issue in dma-buf - Added another patch to enforce minimum `rustc` version for powerpc V12: https://lore.kernel.org/all/20260421120958.190430-1-mkchauras@gmail.com/
V11 -> V12: - Rebased to mainline (rust/Makefile conflict resolved) V11: https://lore.kernel.org/all/20260417152253.2312961-1-mkchauras@gmail.com/
V10 -> V11: - Updated `rust/Makefile` - Not all libraries are move to `rust/host` directory now. Only proc_macro2, quote and syn are moved - Special handling for pin init is added. Details in commit - Removed mkdir for `rust/host`, this is now handled by toolchain. V10: https://lore.kernel.org/all/20260406200149.3727922-1-mkchauras@gmail.com/
V9 -> V10: - rust/Makefile updated with review comments from Miguel - Patch 1/4 updated with commit message and subject V9: https://lore.kernel.org/all/20260404121610.1956528-1-mkchauras@gmail.com/
V8 -> V9: - rust/Makefile updated with a directory instead of abspath V8: https://lore.kernel.org/all/20260403145308.1042622-1-mkchauras@gmail.com/
V7 -> V8: - rust/Makefile updated to separate host libraries from target V7: https://lore.kernel.org/all/20260329160254.2592207-1-mkchauras@gmail.com/
Changelog: V6 -> V7: - Documentation removed as powerpc is still under development - Added a fix for race condition in rust/Makefile V6: https://lore.kernel.org/all/20260210090023.2587534-1-mkchauras@gmail.com
V5 -> V6: - Added a missing Tested by from Venkat which got missed since V3 - Support is marked as Maintained instead of experimental V5: https://lore.kernel.org/all/20260210053756.2088302-1-mkchauras@gmail.com
V4 -> V5: - Removed a nested ifdef from PPC64 for Little endian toolchain V4: https://lore.kernel.org/all/20260209105456.1551677-1-mkchauras@gmail.com
V3 -> V4: - Co-developed-by header added in patch 1 V3: https://lore.kernel.org/all/20260205180429.3280657-1-mkchauras@gmail.com
V2 -> V3: - Splited HAVE_RUST in 2 lines - BINDGEN_TARGET_powerpc initialized before assigning the same to BINDGEN_TARGET V2: https://lore.kernel.org/all/20260204210125.613350-1-mkchauras@gmail.com
V1 -> V2: - jump label fix for rust has been moved to a separate patch - PPC32 support has been taken - rust support has been marked experimental - target.json dependency has been removed - HAVE_RUST now depends on CPU_LITTLE_ENDIAN for PPC64
Link Mauve (2): rust: Make __udivdi3() and __umoddi3() panic rust: Add PowerPC support
Mukesh Kumar Chaurasiya (IBM) (5): rust: Fix "multiple candidates for rmeta dependency core" error dma-resv: Fix undefined symbol when CONFIG_DMA_SHARED_BUFFER is disabled powerpc/jump_label: adjust inline asm to be consistent rust/powerpc: Set min rustc version for powerpc powerpc: Enable Rust for ppc64le
arch/powerpc/Kconfig | 2 ++ arch/powerpc/Makefile | 7 ++++ arch/powerpc/include/asm/jump_label.h | 23 ++++++------ include/linux/dma-resv.h | 2 +- rust/Makefile | 52 +++++++++++++++++---------- rust/compiler_builtins.rs | 6 ++++ scripts/min-tool-version.sh | 6 +++- 7 files changed, 68 insertions(+), 30 deletions(-)
When building Rust code for powerpc64le with LLVM=1 and -j1, rustc encounters an error: "multiple candidates for `rmeta` dependency `core` found", with two candidates: 1. The host's standard library from the rustup toolchain 2. The kernel's custom libcore.rmeta in the rust/ directory
This occurs because the build system uses `-L$(objtree)/rust` for host library builds (proc_macro2, quote, syn), which causes rustc to search the rust/ directory. During this search, rustc finds both the kernel's custom libcore.rmeta and gains access to the host's standard library, creating a conflict.
The solution is to separate host libraries into a dedicated rust/host/ subdirectory and use `-L$(objtree)/rust/host` for host builds instead of `-L$(objtree)/rust`. This ensures that:
1. Host library builds (proc_macro2, quote, syn) only search rust/host/ and never encounter the kernel's libcore.rmeta 2. Proc macro builds use `-L$(objtree)/rust/host` to find their dependencies
Special handling is added for rustdoc-pin_init, which is a host build (to access the alloc crate) but depends on proc macros from the main rust/ directory. It uses explicit `--extern` paths to reference the proc macros without adding `-L$(objtree)/rust`, which would reintroduce the conflict.
The rust/host/ directory is added to clean-files to ensure it's removed during `make clean`.
Link: https://github.com/Rust-for-Linux/linux/issues/105 Link: https://github.com/linuxppc/issues/issues/451 Signed-off-by: Mukesh Kumar Chaurasiya (IBM) mkchauras@gmail.com --- rust/Makefile | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-)
diff --git a/rust/Makefile b/rust/Makefile index b361bfedfdf0..2a5428a5503d 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -3,6 +3,9 @@ # Where to place rustdoc generated documentation rustdoc_output := $(objtree)/Documentation/output/rust/rustdoc
+# Clean generated host directory +clean-files := host/ + obj-$(CONFIG_RUST) += core.o compiler_builtins.o ffi.o always-$(CONFIG_RUST) += exports_core_generated.h
@@ -31,7 +34,7 @@ endif
obj-$(CONFIG_RUST) += exports.o
-always-$(CONFIG_RUST) += libproc_macro2.rlib libquote.rlib libsyn.rlib +always-$(CONFIG_RUST) += host/libproc_macro2.rlib host/libquote.rlib host/libsyn.rlib
always-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated.rs always-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated_kunit.c @@ -146,7 +149,7 @@ quiet_cmd_rustdoc = RUSTDOC $(if $(rustdoc_host),H, ) $< cmd_rustdoc = \ OBJTREE=$(abspath $(objtree)) \ $(RUSTDOC) $(filter-out $(skip_flags) --remap-path-scope=%,$(if $(rustdoc_host),$(rust_common_flags),$(rust_flags))) \ - $(rustc_target_flags) -L$(objtree)/$(obj) \ + $(rustc_target_flags) -L$(objtree)/$(obj)$(if $(rustdoc_host),/host) \ -Zunstable-options --generate-link-to-definition \ --output $(rustdoc_output) \ --crate-name $(subst rustdoc-,,$@) \ @@ -231,6 +234,7 @@ rustdoc-pin_init_internal: $(src)/pin-init/internal/src/lib.rs \
rustdoc-pin_init: private rustdoc_host = yes rustdoc-pin_init: private rustc_target_flags = $(pin_init-flags) \ + --extern pin_init_internal=$(objtree)/$(obj)/$(libpin_init_internal_name) \ --extern alloc --cfg feature="alloc" rustdoc-pin_init: $(src)/pin-init/src/lib.rs rustdoc-pin_init_internal \ rustdoc-macros FORCE @@ -520,23 +524,23 @@ quiet_cmd_rustc_procmacrolibrary = $(RUSTC_OR_CLIPPY_QUIET) PL $@ $(if $(skip_clippy),$(RUSTC),$(RUSTC_OR_CLIPPY)) \ $(filter-out $(skip_flags),$(rust_common_flags) $(rustc_target_flags)) \ --emit=dep-info=$(depfile) --emit=link=$@ --crate-type rlib -O \ - --out-dir $(objtree)/$(obj) -L$(objtree)/$(obj) \ + --out-dir $(objtree)/$(obj)/host -\L$(objtree)/$(obj)/host \ --crate-name $(patsubst lib%.rlib,%,$(notdir $@)) $<
-$(obj)/libproc_macro2.rlib: private skip_clippy = 1 -$(obj)/libproc_macro2.rlib: private rustc_target_flags = $(proc_macro2-flags) -$(obj)/libproc_macro2.rlib: $(src)/proc-macro2/lib.rs FORCE +$(obj)/host/libproc_macro2.rlib: private skip_clippy = 1 +$(obj)/host/libproc_macro2.rlib: private rustc_target_flags = $(proc_macro2-flags) +$(obj)/host/libproc_macro2.rlib: $(src)/proc-macro2/lib.rs FORCE +$(call if_changed_dep,rustc_procmacrolibrary)
-$(obj)/libquote.rlib: private skip_clippy = 1 -$(obj)/libquote.rlib: private skip_flags = $(quote-skip_flags) -$(obj)/libquote.rlib: private rustc_target_flags = $(quote-flags) -$(obj)/libquote.rlib: $(src)/quote/lib.rs $(obj)/libproc_macro2.rlib FORCE +$(obj)/host/libquote.rlib: private skip_clippy = 1 +$(obj)/host/libquote.rlib: private skip_flags = $(quote-skip_flags) +$(obj)/host/libquote.rlib: private rustc_target_flags = $(quote-flags) +$(obj)/host/libquote.rlib: $(src)/quote/lib.rs $(obj)/host/libproc_macro2.rlib FORCE +$(call if_changed_dep,rustc_procmacrolibrary)
-$(obj)/libsyn.rlib: private skip_clippy = 1 -$(obj)/libsyn.rlib: private rustc_target_flags = $(syn-flags) -$(obj)/libsyn.rlib: $(src)/syn/lib.rs $(obj)/libquote.rlib FORCE +$(obj)/host/libsyn.rlib: private skip_clippy = 1 +$(obj)/host/libsyn.rlib: private rustc_target_flags = $(syn-flags) +$(obj)/host/libsyn.rlib: $(src)/syn/lib.rs $(obj)/host/libquote.rlib FORCE +$(call if_changed_dep,rustc_procmacrolibrary)
quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@ @@ -545,20 +549,20 @@ quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@ -Clinker-flavor=gcc -Clinker=$(HOSTCC) \ -Clink-args='$(call escsq,$(KBUILD_PROCMACROLDFLAGS))' \ --emit=dep-info=$(depfile) --emit=link=$@ --extern proc_macro \ - --crate-type proc-macro -L$(objtree)/$(obj) \ + --crate-type proc-macro -L$(objtree)/$(obj)/host \ --crate-name $(patsubst lib%.$(libmacros_extension),%,$(notdir $@)) \ @$(objtree)/include/generated/rustc_cfg $<
# Procedural macros can only be used with the `rustc` that compiled it. $(obj)/$(libmacros_name): private rustc_target_flags = \ --extern proc_macro2 --extern quote --extern syn -$(obj)/$(libmacros_name): $(src)/macros/lib.rs $(obj)/libproc_macro2.rlib \ - $(obj)/libquote.rlib $(obj)/libsyn.rlib FORCE +$(obj)/$(libmacros_name): $(src)/macros/lib.rs $(obj)/host/libproc_macro2.rlib \ + $(obj)/host/libquote.rlib $(obj)/host/libsyn.rlib FORCE +$(call if_changed_dep,rustc_procmacro)
$(obj)/$(libpin_init_internal_name): private rustc_target_flags = $(pin_init_internal-flags) $(obj)/$(libpin_init_internal_name): $(src)/pin-init/internal/src/lib.rs \ - $(obj)/libproc_macro2.rlib $(obj)/libquote.rlib $(obj)/libsyn.rlib FORCE + $(obj)/host/libproc_macro2.rlib $(obj)/host/libquote.rlib $(obj)/host/libsyn.rlib FORCE +$(call if_changed_dep,rustc_procmacro)
# `rustc` requires `-Zunstable-options` to use custom target specifications
When building with LLVM=1 for architectures like powerpc where CONFIG_DMA_SHARED_BUFFER is not enabled, the build fails with:
ld.lld: error: undefined symbol: dma_resv_reset_max_fences
referenced by helpers.c rust/helpers/helpers.o:(rust_helper_dma_resv_unlock)
The issue occurs because: 1. CONFIG_DEBUG_MUTEXES=y is enabled 2. CONFIG_DMA_SHARED_BUFFER is not enabled 3. dma_resv_reset_max_fences() is declared in the header when CONFIG_DEBUG_MUTEXES is set 4. But the function is only compiled in drivers/dma-buf/dma-resv.c, which is only built when CONFIG_DMA_SHARED_BUFFER is enabled 5. Rust helpers call dma_resv_unlock() which calls dma_resv_reset_max_fences(), causing an undefined symbol
Fix this by making the function declaration conditional on both CONFIG_DEBUG_MUTEXES and CONFIG_DMA_SHARED_BUFFER. When either is disabled, use a static inline stub instead.
Fixes: 0c6b522abc2a ("dma-buf: cleanup dma-resv shared fence debugging a bit v2") Signed-off-by: Mukesh Kumar Chaurasiya (IBM) mkchauras@gmail.com --- include/linux/dma-resv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/linux/dma-resv.h b/include/linux/dma-resv.h index c5ab6fd9ebe8..23c8db0b5214 100644 --- a/include/linux/dma-resv.h +++ b/include/linux/dma-resv.h @@ -311,7 +311,7 @@ static inline bool dma_resv_iter_is_restarted(struct dma_resv_iter *cursor) #define dma_resv_held(obj) lockdep_is_held(&(obj)->lock.base) #define dma_resv_assert_held(obj) lockdep_assert_held(&(obj)->lock.base)
-#ifdef CONFIG_DEBUG_MUTEXES +#if IS_ENABLED(CONFIG_DEBUG_MUTEXES) && IS_ENABLED(CONFIG_DMA_SHARED_BUFFER) void dma_resv_reset_max_fences(struct dma_resv *obj); #else static inline void dma_resv_reset_max_fences(struct dma_resv *obj) {}
On 4/24/26 07:47, Mukesh Kumar Chaurasiya (IBM) wrote:
When building with LLVM=1 for architectures like powerpc where CONFIG_DMA_SHARED_BUFFER is not enabled, the build fails with:
ld.lld: error: undefined symbol: dma_resv_reset_max_fences
referenced by helpers.c rust/helpers/helpers.o:(rust_helper_dma_resv_unlock)
The issue occurs because:
- CONFIG_DEBUG_MUTEXES=y is enabled
- CONFIG_DMA_SHARED_BUFFER is not enabled
- dma_resv_reset_max_fences() is declared in the header when CONFIG_DEBUG_MUTEXES is set
- But the function is only compiled in drivers/dma-buf/dma-resv.c, which is only built when CONFIG_DMA_SHARED_BUFFER is enabled
- Rust helpers call dma_resv_unlock() which calls dma_resv_reset_max_fences(), causing an undefined symbol
Fix this by making the function declaration conditional on both CONFIG_DEBUG_MUTEXES and CONFIG_DMA_SHARED_BUFFER. When either is disabled, use a static inline stub instead.
Well we are clearly missing something here, but of hand that doesn't looks like the right fix.
When CONFIG_DMA_SHARED_BUFFER isn't enabled then the whole dma-resv.h header can't be used at all.
So you also can't call dma_resv_unlock() from the Rust helpers. Which means that we need to make the Rust helpers somehow depend on CONFIG_DMA_SHARED_BUFFER.
Alternative would be to provide dummies for the functions in dma-resv.h when CONFIG_DMA_SHARED_BUFFER isn't set, but that looks a bit like it just hides the issue.
Regards, Christian.
Fixes: 0c6b522abc2a ("dma-buf: cleanup dma-resv shared fence debugging a bit v2") Signed-off-by: Mukesh Kumar Chaurasiya (IBM) mkchauras@gmail.com
include/linux/dma-resv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/linux/dma-resv.h b/include/linux/dma-resv.h index c5ab6fd9ebe8..23c8db0b5214 100644 --- a/include/linux/dma-resv.h +++ b/include/linux/dma-resv.h @@ -311,7 +311,7 @@ static inline bool dma_resv_iter_is_restarted(struct dma_resv_iter *cursor) #define dma_resv_held(obj) lockdep_is_held(&(obj)->lock.base) #define dma_resv_assert_held(obj) lockdep_assert_held(&(obj)->lock.base)
-#ifdef CONFIG_DEBUG_MUTEXES +#if IS_ENABLED(CONFIG_DEBUG_MUTEXES) && IS_ENABLED(CONFIG_DMA_SHARED_BUFFER) void dma_resv_reset_max_fences(struct dma_resv *obj); #else static inline void dma_resv_reset_max_fences(struct dma_resv *obj) {} -- 2.53.0
On Fri, Apr 24, 2026 at 09:56:16AM +0200, Christian König wrote:
On 4/24/26 07:47, Mukesh Kumar Chaurasiya (IBM) wrote:
When building with LLVM=1 for architectures like powerpc where CONFIG_DMA_SHARED_BUFFER is not enabled, the build fails with:
ld.lld: error: undefined symbol: dma_resv_reset_max_fences
referenced by helpers.c rust/helpers/helpers.o:(rust_helper_dma_resv_unlock)
The issue occurs because:
- CONFIG_DEBUG_MUTEXES=y is enabled
- CONFIG_DMA_SHARED_BUFFER is not enabled
- dma_resv_reset_max_fences() is declared in the header when CONFIG_DEBUG_MUTEXES is set
- But the function is only compiled in drivers/dma-buf/dma-resv.c, which is only built when CONFIG_DMA_SHARED_BUFFER is enabled
- Rust helpers call dma_resv_unlock() which calls dma_resv_reset_max_fences(), causing an undefined symbol
Fix this by making the function declaration conditional on both CONFIG_DEBUG_MUTEXES and CONFIG_DMA_SHARED_BUFFER. When either is disabled, use a static inline stub instead.
Well we are clearly missing something here, but of hand that doesn't looks like the right fix.
When CONFIG_DMA_SHARED_BUFFER isn't enabled then the whole dma-resv.h header can't be used at all.
So you also can't call dma_resv_unlock() from the Rust helpers. Which means that we need to make the Rust helpers somehow depend on CONFIG_DMA_SHARED_BUFFER.
Alternative would be to provide dummies for the functions in dma-resv.h when CONFIG_DMA_SHARED_BUFFER isn't set, but that looks a bit like it just hides the issue.
Regards, Christian.
What about something like this:
diff --git a/rust/helpers/dma-resv.c b/rust/helpers/dma-resv.c index 71914d8241e2..53c119f1b144 100644 --- a/rust/helpers/dma-resv.c +++ b/rust/helpers/dma-resv.c @@ -2,6 +2,7 @@
#include <linux/dma-resv.h>
+#ifdef CONFIG_DMA_SHARED_BUFFER __rust_helper int rust_helper_dma_resv_lock(struct dma_resv *obj, struct ww_acquire_ctx *ctx) { @@ -12,3 +13,4 @@ __rust_helper void rust_helper_dma_resv_unlock(struct dma_resv *obj) { dma_resv_unlock(obj); } +#endif
This seems to fix the issue and makes sense, whoever wants to use the dma shared buffer will anyway enable the config
Regards, Mukesh
Fixes: 0c6b522abc2a ("dma-buf: cleanup dma-resv shared fence debugging a bit v2") Signed-off-by: Mukesh Kumar Chaurasiya (IBM) mkchauras@gmail.com
include/linux/dma-resv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/linux/dma-resv.h b/include/linux/dma-resv.h index c5ab6fd9ebe8..23c8db0b5214 100644 --- a/include/linux/dma-resv.h +++ b/include/linux/dma-resv.h @@ -311,7 +311,7 @@ static inline bool dma_resv_iter_is_restarted(struct dma_resv_iter *cursor) #define dma_resv_held(obj) lockdep_is_held(&(obj)->lock.base) #define dma_resv_assert_held(obj) lockdep_assert_held(&(obj)->lock.base)
-#ifdef CONFIG_DEBUG_MUTEXES +#if IS_ENABLED(CONFIG_DEBUG_MUTEXES) && IS_ENABLED(CONFIG_DMA_SHARED_BUFFER) void dma_resv_reset_max_fences(struct dma_resv *obj); #else static inline void dma_resv_reset_max_fences(struct dma_resv *obj) {} -- 2.53.0
On 4/24/26 10:06, Mukesh Kumar Chaurasiya wrote:
[Sie erhalten nicht häufig E-Mails von mkchauras@gmail.com. Weitere Informationen, warum dies wichtig ist, finden Sie unter https://aka.ms/LearnAboutSenderIdentification ]
On Fri, Apr 24, 2026 at 09:56:16AM +0200, Christian König wrote:
On 4/24/26 07:47, Mukesh Kumar Chaurasiya (IBM) wrote:
When building with LLVM=1 for architectures like powerpc where CONFIG_DMA_SHARED_BUFFER is not enabled, the build fails with:
ld.lld: error: undefined symbol: dma_resv_reset_max_fences
referenced by helpers.c rust/helpers/helpers.o:(rust_helper_dma_resv_unlock)
The issue occurs because:
- CONFIG_DEBUG_MUTEXES=y is enabled
- CONFIG_DMA_SHARED_BUFFER is not enabled
- dma_resv_reset_max_fences() is declared in the header when CONFIG_DEBUG_MUTEXES is set
- But the function is only compiled in drivers/dma-buf/dma-resv.c, which is only built when CONFIG_DMA_SHARED_BUFFER is enabled
- Rust helpers call dma_resv_unlock() which calls dma_resv_reset_max_fences(), causing an undefined symbol
Fix this by making the function declaration conditional on both CONFIG_DEBUG_MUTEXES and CONFIG_DMA_SHARED_BUFFER. When either is disabled, use a static inline stub instead.
Well we are clearly missing something here, but of hand that doesn't looks like the right fix.
When CONFIG_DMA_SHARED_BUFFER isn't enabled then the whole dma-resv.h header can't be used at all.
So you also can't call dma_resv_unlock() from the Rust helpers. Which means that we need to make the Rust helpers somehow depend on CONFIG_DMA_SHARED_BUFFER.
Alternative would be to provide dummies for the functions in dma-resv.h when CONFIG_DMA_SHARED_BUFFER isn't set, but that looks a bit like it just hides the issue.
Regards, Christian.
What about something like this:
diff --git a/rust/helpers/dma-resv.c b/rust/helpers/dma-resv.c index 71914d8241e2..53c119f1b144 100644 --- a/rust/helpers/dma-resv.c +++ b/rust/helpers/dma-resv.c @@ -2,6 +2,7 @@
#include <linux/dma-resv.h>
+#ifdef CONFIG_DMA_SHARED_BUFFER __rust_helper int rust_helper_dma_resv_lock(struct dma_resv *obj, struct ww_acquire_ctx *ctx) { @@ -12,3 +13,4 @@ __rust_helper void rust_helper_dma_resv_unlock(struct dma_resv *obj) { dma_resv_unlock(obj); } +#endif
This seems to fix the issue and makes sense, whoever wants to use the dma shared buffer will anyway enable the config
Yeah that directions makes sense.
I would maybe go a step further and don't even compile rust/helpers/dma-resv.c when CONFIG_DMA_SHARED_BUFFER isn't set.
But if that is not possible for some reason then this solution is perfectly fine with me as well.
The general goal is to make the error messages when you haven't set CONFIG_DMA_SHARED_BUFFER and still try to use the DMA-buf functions easy to understand and not something cryptic.
Thanks, Christian.
Regards, Mukesh
Fixes: 0c6b522abc2a ("dma-buf: cleanup dma-resv shared fence debugging a bit v2") Signed-off-by: Mukesh Kumar Chaurasiya (IBM) mkchauras@gmail.com
include/linux/dma-resv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/linux/dma-resv.h b/include/linux/dma-resv.h index c5ab6fd9ebe8..23c8db0b5214 100644 --- a/include/linux/dma-resv.h +++ b/include/linux/dma-resv.h @@ -311,7 +311,7 @@ static inline bool dma_resv_iter_is_restarted(struct dma_resv_iter *cursor) #define dma_resv_held(obj) lockdep_is_held(&(obj)->lock.base) #define dma_resv_assert_held(obj) lockdep_assert_held(&(obj)->lock.base)
-#ifdef CONFIG_DEBUG_MUTEXES +#if IS_ENABLED(CONFIG_DEBUG_MUTEXES) && IS_ENABLED(CONFIG_DMA_SHARED_BUFFER) void dma_resv_reset_max_fences(struct dma_resv *obj); #else static inline void dma_resv_reset_max_fences(struct dma_resv *obj) {} -- 2.53.0
On Fri, Apr 24, 2026 at 10:25:25AM +0200, Christian König wrote:
On 4/24/26 10:06, Mukesh Kumar Chaurasiya wrote:
[Sie erhalten nicht häufig E-Mails von mkchauras@gmail.com. Weitere Informationen, warum dies wichtig ist, finden Sie unter https://aka.ms/LearnAboutSenderIdentification ]
On Fri, Apr 24, 2026 at 09:56:16AM +0200, Christian König wrote:
On 4/24/26 07:47, Mukesh Kumar Chaurasiya (IBM) wrote:
When building with LLVM=1 for architectures like powerpc where CONFIG_DMA_SHARED_BUFFER is not enabled, the build fails with:
ld.lld: error: undefined symbol: dma_resv_reset_max_fences
> referenced by helpers.c > rust/helpers/helpers.o:(rust_helper_dma_resv_unlock)
The issue occurs because:
- CONFIG_DEBUG_MUTEXES=y is enabled
- CONFIG_DMA_SHARED_BUFFER is not enabled
- dma_resv_reset_max_fences() is declared in the header when CONFIG_DEBUG_MUTEXES is set
- But the function is only compiled in drivers/dma-buf/dma-resv.c, which is only built when CONFIG_DMA_SHARED_BUFFER is enabled
- Rust helpers call dma_resv_unlock() which calls dma_resv_reset_max_fences(), causing an undefined symbol
Fix this by making the function declaration conditional on both CONFIG_DEBUG_MUTEXES and CONFIG_DMA_SHARED_BUFFER. When either is disabled, use a static inline stub instead.
Well we are clearly missing something here, but of hand that doesn't looks like the right fix.
When CONFIG_DMA_SHARED_BUFFER isn't enabled then the whole dma-resv.h header can't be used at all.
So you also can't call dma_resv_unlock() from the Rust helpers. Which means that we need to make the Rust helpers somehow depend on CONFIG_DMA_SHARED_BUFFER.
Alternative would be to provide dummies for the functions in dma-resv.h when CONFIG_DMA_SHARED_BUFFER isn't set, but that looks a bit like it just hides the issue.
Regards, Christian.
What about something like this:
diff --git a/rust/helpers/dma-resv.c b/rust/helpers/dma-resv.c index 71914d8241e2..53c119f1b144 100644 --- a/rust/helpers/dma-resv.c +++ b/rust/helpers/dma-resv.c @@ -2,6 +2,7 @@
#include <linux/dma-resv.h>
+#ifdef CONFIG_DMA_SHARED_BUFFER __rust_helper int rust_helper_dma_resv_lock(struct dma_resv *obj, struct ww_acquire_ctx *ctx) { @@ -12,3 +13,4 @@ __rust_helper void rust_helper_dma_resv_unlock(struct dma_resv *obj) { dma_resv_unlock(obj); } +#endif
This seems to fix the issue and makes sense, whoever wants to use the dma shared buffer will anyway enable the config
Yeah that directions makes sense.
I would maybe go a step further and don't even compile rust/helpers/dma-resv.c when CONFIG_DMA_SHARED_BUFFER isn't set.
This makes sense.
But if that is not possible for some reason then this solution is perfectly fine with me as well.
The general goal is to make the error messages when you haven't set CONFIG_DMA_SHARED_BUFFER and still try to use the DMA-buf functions easy to understand and not something cryptic.
Thanks, Christian.
What about this one?
diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c index 625921e27dfb..09ee5cac600d 100644 --- a/rust/helpers/helpers.c +++ b/rust/helpers/helpers.c @@ -57,7 +57,9 @@ #include "cred.c" #include "device.c" #include "dma.c" +#ifdef CONFIG_DMA_SHARED_BUFFER #include "dma-resv.c" +#endif #include "drm.c" #include "err.c" #include "irq.c"
Regards, Mukesh
Regards, Mukesh
Fixes: 0c6b522abc2a ("dma-buf: cleanup dma-resv shared fence debugging a bit v2") Signed-off-by: Mukesh Kumar Chaurasiya (IBM) mkchauras@gmail.com
include/linux/dma-resv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/linux/dma-resv.h b/include/linux/dma-resv.h index c5ab6fd9ebe8..23c8db0b5214 100644 --- a/include/linux/dma-resv.h +++ b/include/linux/dma-resv.h @@ -311,7 +311,7 @@ static inline bool dma_resv_iter_is_restarted(struct dma_resv_iter *cursor) #define dma_resv_held(obj) lockdep_is_held(&(obj)->lock.base) #define dma_resv_assert_held(obj) lockdep_assert_held(&(obj)->lock.base)
-#ifdef CONFIG_DEBUG_MUTEXES +#if IS_ENABLED(CONFIG_DEBUG_MUTEXES) && IS_ENABLED(CONFIG_DMA_SHARED_BUFFER) void dma_resv_reset_max_fences(struct dma_resv *obj); #else static inline void dma_resv_reset_max_fences(struct dma_resv *obj) {} -- 2.53.0
On 4/24/26 10:34, Mukesh Kumar Chaurasiya wrote:
On Fri, Apr 24, 2026 at 10:25:25AM +0200, Christian König wrote:
On 4/24/26 10:06, Mukesh Kumar Chaurasiya wrote:
[Sie erhalten nicht häufig E-Mails von mkchauras@gmail.com. Weitere Informationen, warum dies wichtig ist, finden Sie unter https://aka.ms/LearnAboutSenderIdentification ]
On Fri, Apr 24, 2026 at 09:56:16AM +0200, Christian König wrote:
On 4/24/26 07:47, Mukesh Kumar Chaurasiya (IBM) wrote:
When building with LLVM=1 for architectures like powerpc where CONFIG_DMA_SHARED_BUFFER is not enabled, the build fails with:
ld.lld: error: undefined symbol: dma_resv_reset_max_fences
>> referenced by helpers.c >> rust/helpers/helpers.o:(rust_helper_dma_resv_unlock)
The issue occurs because:
- CONFIG_DEBUG_MUTEXES=y is enabled
- CONFIG_DMA_SHARED_BUFFER is not enabled
- dma_resv_reset_max_fences() is declared in the header when CONFIG_DEBUG_MUTEXES is set
- But the function is only compiled in drivers/dma-buf/dma-resv.c, which is only built when CONFIG_DMA_SHARED_BUFFER is enabled
- Rust helpers call dma_resv_unlock() which calls dma_resv_reset_max_fences(), causing an undefined symbol
Fix this by making the function declaration conditional on both CONFIG_DEBUG_MUTEXES and CONFIG_DMA_SHARED_BUFFER. When either is disabled, use a static inline stub instead.
Well we are clearly missing something here, but of hand that doesn't looks like the right fix.
When CONFIG_DMA_SHARED_BUFFER isn't enabled then the whole dma-resv.h header can't be used at all.
So you also can't call dma_resv_unlock() from the Rust helpers. Which means that we need to make the Rust helpers somehow depend on CONFIG_DMA_SHARED_BUFFER.
Alternative would be to provide dummies for the functions in dma-resv.h when CONFIG_DMA_SHARED_BUFFER isn't set, but that looks a bit like it just hides the issue.
Regards, Christian.
What about something like this:
diff --git a/rust/helpers/dma-resv.c b/rust/helpers/dma-resv.c index 71914d8241e2..53c119f1b144 100644 --- a/rust/helpers/dma-resv.c +++ b/rust/helpers/dma-resv.c @@ -2,6 +2,7 @@
#include <linux/dma-resv.h>
+#ifdef CONFIG_DMA_SHARED_BUFFER __rust_helper int rust_helper_dma_resv_lock(struct dma_resv *obj, struct ww_acquire_ctx *ctx) { @@ -12,3 +13,4 @@ __rust_helper void rust_helper_dma_resv_unlock(struct dma_resv *obj) { dma_resv_unlock(obj); } +#endif
This seems to fix the issue and makes sense, whoever wants to use the dma shared buffer will anyway enable the config
Yeah that directions makes sense.
I would maybe go a step further and don't even compile rust/helpers/dma-resv.c when CONFIG_DMA_SHARED_BUFFER isn't set.
This makes sense.
But if that is not possible for some reason then this solution is perfectly fine with me as well.
The general goal is to make the error messages when you haven't set CONFIG_DMA_SHARED_BUFFER and still try to use the DMA-buf functions easy to understand and not something cryptic.
Thanks, Christian.
What about this one?
diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c index 625921e27dfb..09ee5cac600d 100644 --- a/rust/helpers/helpers.c +++ b/rust/helpers/helpers.c @@ -57,7 +57,9 @@ #include "cred.c" #include "device.c" #include "dma.c" +#ifdef CONFIG_DMA_SHARED_BUFFER #include "dma-resv.c" +#endif #include "drm.c" #include "err.c" #include "irq.c"
Looks good, feel free to add Reviewed-by: Christian König christian.koenig@amd.com
But somebody more familiar with the Rust helpers should take another look on it.
Regards, Christian.
Regards, Mukesh
Regards, Mukesh
Fixes: 0c6b522abc2a ("dma-buf: cleanup dma-resv shared fence debugging a bit v2") Signed-off-by: Mukesh Kumar Chaurasiya (IBM) mkchauras@gmail.com
include/linux/dma-resv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/linux/dma-resv.h b/include/linux/dma-resv.h index c5ab6fd9ebe8..23c8db0b5214 100644 --- a/include/linux/dma-resv.h +++ b/include/linux/dma-resv.h @@ -311,7 +311,7 @@ static inline bool dma_resv_iter_is_restarted(struct dma_resv_iter *cursor) #define dma_resv_held(obj) lockdep_is_held(&(obj)->lock.base) #define dma_resv_assert_held(obj) lockdep_assert_held(&(obj)->lock.base)
-#ifdef CONFIG_DEBUG_MUTEXES +#if IS_ENABLED(CONFIG_DEBUG_MUTEXES) && IS_ENABLED(CONFIG_DMA_SHARED_BUFFER) void dma_resv_reset_max_fences(struct dma_resv *obj); #else static inline void dma_resv_reset_max_fences(struct dma_resv *obj) {} -- 2.53.0
Added support for a new macro ARCH_STATIC_BRANCH_ASM in powerpc to avoid duplication of inline asm between C and Rust. This is inline with 'commit aecaf181651c ("jump_label: adjust inline asm to be consistent")'
Co-developed-by: Madhavan Srinivasan maddy@linux.ibm.com Signed-off-by: Madhavan Srinivasan maddy@linux.ibm.com Reviewed-by: Alice Ryhl aliceryhl@google.com Reviewed-by: Christophe Leroy (CS GROUP) chleroy@kernel.org Reviewed-by: Gary Guo gary@garyguo.net Link: https://github.com/Rust-for-Linux/linux/issues/105 Link: https://github.com/linuxppc/issues/issues/451 Signed-off-by: Mukesh Kumar Chaurasiya (IBM) mkchauras@gmail.com --- arch/powerpc/include/asm/jump_label.h | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-)
diff --git a/arch/powerpc/include/asm/jump_label.h b/arch/powerpc/include/asm/jump_label.h index d4eaba459a0e..3016e9c8d6bc 100644 --- a/arch/powerpc/include/asm/jump_label.h +++ b/arch/powerpc/include/asm/jump_label.h @@ -15,14 +15,20 @@ #define JUMP_ENTRY_TYPE stringify_in_c(FTR_ENTRY_LONG) #define JUMP_LABEL_NOP_SIZE 4
+#define JUMP_TABLE_ENTRY(key, label) \ + ".pushsection __jump_table, "aw" \n\t" \ + ".long 1b - ., " label " - . \n\t" \ + JUMP_ENTRY_TYPE key " - . \n\t" \ + ".popsection \n\t" + +#define ARCH_STATIC_BRANCH_ASM(key, label) \ + "1: nop \n\t" \ + JUMP_TABLE_ENTRY(key, label) + static __always_inline bool arch_static_branch(struct static_key *key, bool branch) { - asm goto("1:\n\t" - "nop # arch_static_branch\n\t" - ".pushsection __jump_table, "aw"\n\t" - ".long 1b - ., %l[l_yes] - .\n\t" - JUMP_ENTRY_TYPE "%c0 - .\n\t" - ".popsection \n\t" + asm goto( + ARCH_STATIC_BRANCH_ASM("%c0", "%l[l_yes]") : : "i" (&((char *)key)[branch]) : : l_yes);
return false; @@ -34,10 +40,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool { asm goto("1:\n\t" "b %l[l_yes] # arch_static_branch_jump\n\t" - ".pushsection __jump_table, "aw"\n\t" - ".long 1b - ., %l[l_yes] - .\n\t" - JUMP_ENTRY_TYPE "%c0 - .\n\t" - ".popsection \n\t" + JUMP_TABLE_ENTRY("%c0", "%l[l_yes]") : : "i" (&((char *)key)[branch]) : : l_yes);
return false;
Minimum `rustc` version required for powerpc is 1.95 as some critical features required for compiling rust code for kernel is not there.
For e.g. Stable inline asm support which got merged in 1.95.
Link: https://github.com/rust-lang/rust/pull/147996 Signed-off-by: Mukesh Kumar Chaurasiya (IBM) mkchauras@gmail.com --- scripts/min-tool-version.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/scripts/min-tool-version.sh b/scripts/min-tool-version.sh index b96ec2d379b6..406895621511 100755 --- a/scripts/min-tool-version.sh +++ b/scripts/min-tool-version.sh @@ -31,7 +31,11 @@ llvm) fi ;; rustc) - echo 1.85.0 + if [ "$ARCH" = powerpc ]; then + echo 1.95.0 + else + echo 1.85.0 + fi ;; bindgen) echo 0.71.1
From: Link Mauve linkmauve@linkmauve.fr
The core crate currently depends on these two functions for i64/u64/ i128/u128/core::time::Duration formatting, but we shouldn’t use that in the kernel so let’s panic if they are ever called.
This doesn’t yet fix drm_panic_qr.rs, which also uses __udivdi3 when CONFIG_CC_OPTIMIZE_FOR_SIZE=y, but at least makes the rest of the kernel build on PPC32.
Signed-off-by: Link Mauve linkmauve@linkmauve.fr Signed-off-by: Mukesh Kumar Chaurasiya (IBM) mkchauras@gmail.com --- rust/Makefile | 4 ++++ rust/compiler_builtins.rs | 6 ++++++ 2 files changed, 10 insertions(+)
diff --git a/rust/Makefile b/rust/Makefile index 2a5428a5503d..ee11fba7a03d 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -616,6 +616,10 @@ ifneq ($(or $(CONFIG_ARM64),$(and $(CONFIG_RISCV),$(CONFIG_64BIT))),) __ashrti3 \ __ashlti3 __lshrti3 endif +ifdef CONFIG_PPC32 + redirect-intrinsics += \ + __udivdi3 __umoddi3 +endif
ifdef CONFIG_MODVERSIONS cmd_gendwarfksyms = $(if $(skip_gendwarfksyms),, \ diff --git a/rust/compiler_builtins.rs b/rust/compiler_builtins.rs index dd16c1dc899c..fc6b54636dd5 100644 --- a/rust/compiler_builtins.rs +++ b/rust/compiler_builtins.rs @@ -97,5 +97,11 @@ pub extern "C" fn $ident() { __aeabi_uldivmod, });
+#[cfg(target_arch = "powerpc")] +define_panicking_intrinsics!("`u64` division/modulo should not be used", { + __udivdi3, + __umoddi3, +}); + // NOTE: if you are adding a new intrinsic here, you should also add it to // `redirect-intrinsics` in `rust/Makefile`.
On Fri, Apr 24, 2026, at 07:47, Mukesh Kumar Chaurasiya (IBM) wrote:
This doesn’t yet fix drm_panic_qr.rs, which also uses __udivdi3 when CONFIG_CC_OPTIMIZE_FOR_SIZE=y, but at least makes the rest of the kernel build on PPC32.
It looks like the problem is commit 9af8f2b469c0 ("drm/panic: Add a u64 divide by 10 for arm32") describing this as an arm32 specific issue rather than something common for any 32-bit architecture.
You can probably add a rust version of div_u64() and use that there.
Arnd
On Fri, 24 Apr 2026 11:17:40 +0530 "Mukesh Kumar Chaurasiya (IBM)" mkchauras@gmail.com wrote:
From: Link Mauve linkmauve@linkmauve.fr
The core crate currently depends on these two functions for i64/u64/ i128/u128/core::time::Duration formatting, but we shouldn’t use that in the kernel so let’s panic if they are ever called.
Ugg. Surely you can make it a link-time failure? Or change the underlying code to avoid the divide.
David
This doesn’t yet fix drm_panic_qr.rs, which also uses __udivdi3 when CONFIG_CC_OPTIMIZE_FOR_SIZE=y, but at least makes the rest of the kernel build on PPC32.
Signed-off-by: Link Mauve linkmauve@linkmauve.fr Signed-off-by: Mukesh Kumar Chaurasiya (IBM) mkchauras@gmail.com
rust/Makefile | 4 ++++ rust/compiler_builtins.rs | 6 ++++++ 2 files changed, 10 insertions(+)
diff --git a/rust/Makefile b/rust/Makefile index 2a5428a5503d..ee11fba7a03d 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -616,6 +616,10 @@ ifneq ($(or $(CONFIG_ARM64),$(and $(CONFIG_RISCV),$(CONFIG_64BIT))),) __ashrti3 \ __ashlti3 __lshrti3 endif +ifdef CONFIG_PPC32
- redirect-intrinsics += \
__udivdi3 __umoddi3+endif ifdef CONFIG_MODVERSIONS cmd_gendwarfksyms = $(if $(skip_gendwarfksyms),, \ diff --git a/rust/compiler_builtins.rs b/rust/compiler_builtins.rs index dd16c1dc899c..fc6b54636dd5 100644 --- a/rust/compiler_builtins.rs +++ b/rust/compiler_builtins.rs @@ -97,5 +97,11 @@ pub extern "C" fn $ident() { __aeabi_uldivmod, }); +#[cfg(target_arch = "powerpc")] +define_panicking_intrinsics!("`u64` division/modulo should not be used", {
- __udivdi3,
- __umoddi3,
+});
// NOTE: if you are adding a new intrinsic here, you should also add it to // `redirect-intrinsics` in `rust/Makefile`.
On Fri, Apr 24, 2026 at 10:14:25AM +0100, David Laight wrote:
On Fri, 24 Apr 2026 11:17:40 +0530 "Mukesh Kumar Chaurasiya (IBM)" mkchauras@gmail.com wrote:
From: Link Mauve linkmauve@linkmauve.fr
The core crate currently depends on these two functions for i64/u64/ i128/u128/core::time::Duration formatting, but we shouldn’t use that in the kernel so let’s panic if they are ever called.
Ugg. Surely you can make it a link-time failure? Or change the underlying code to avoid the divide.
This is currently a link-time failure, which means if any of the core crate or drm_panic_qr are linked in, the kernel will fail to link.
And since we rely on core, that means no kernel can be built on PowerPC without this patch.
A possible solution would be to change the core crate to not divide u64s, but the last time I tried to do that I couldn’t quite figure out how to do formatting without it, maybe I will just open an issue against Rust.
David
This doesn’t yet fix drm_panic_qr.rs, which also uses __udivdi3 when CONFIG_CC_OPTIMIZE_FOR_SIZE=y, but at least makes the rest of the kernel build on PPC32.
Signed-off-by: Link Mauve linkmauve@linkmauve.fr Signed-off-by: Mukesh Kumar Chaurasiya (IBM) mkchauras@gmail.com
rust/Makefile | 4 ++++ rust/compiler_builtins.rs | 6 ++++++ 2 files changed, 10 insertions(+)
diff --git a/rust/Makefile b/rust/Makefile index 2a5428a5503d..ee11fba7a03d 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -616,6 +616,10 @@ ifneq ($(or $(CONFIG_ARM64),$(and $(CONFIG_RISCV),$(CONFIG_64BIT))),) __ashrti3 \ __ashlti3 __lshrti3 endif +ifdef CONFIG_PPC32
- redirect-intrinsics += \
__udivdi3 __umoddi3+endif ifdef CONFIG_MODVERSIONS cmd_gendwarfksyms = $(if $(skip_gendwarfksyms),, \ diff --git a/rust/compiler_builtins.rs b/rust/compiler_builtins.rs index dd16c1dc899c..fc6b54636dd5 100644 --- a/rust/compiler_builtins.rs +++ b/rust/compiler_builtins.rs @@ -97,5 +97,11 @@ pub extern "C" fn $ident() { __aeabi_uldivmod, }); +#[cfg(target_arch = "powerpc")] +define_panicking_intrinsics!("`u64` division/modulo should not be used", {
- __udivdi3,
- __umoddi3,
+});
// NOTE: if you are adding a new intrinsic here, you should also add it to // `redirect-intrinsics` in `rust/Makefile`.
On Fri, Apr 24, 2026, at 11:43, Link Mauve wrote:
On Fri, Apr 24, 2026 at 10:14:25AM +0100, David Laight wrote:
On Fri, 24 Apr 2026 11:17:40 +0530 "Mukesh Kumar Chaurasiya (IBM)" mkchauras@gmail.com wrote:
From: Link Mauve linkmauve@linkmauve.fr
The core crate currently depends on these two functions for i64/u64/ i128/u128/core::time::Duration formatting, but we shouldn’t use that in the kernel so let’s panic if they are ever called.
Ugg. Surely you can make it a link-time failure? Or change the underlying code to avoid the divide.
This is currently a link-time failure, which means if any of the core crate or drm_panic_qr are linked in, the kernel will fail to link.
And since we rely on core, that means no kernel can be built on PowerPC without this patch.
A possible solution would be to change the core crate to not divide u64s, but the last time I tried to do that I couldn’t quite figure out how to do formatting without it, maybe I will just open an issue against Rust.
How hard would it be to have a private copy of the parts of the core crate that the kernel actually needs? Since Linux is neither quite hosted (using a full libc) nor entirely freestanding (still using some library interfaces), the C implementation on most architectures has a small subset of the libgcc that we ship with the kernel.
I assume the core crate is larger than libgcc, but I don't know how much of it is actually needed here.
Arnd
On Fri, Apr 24, 2026 at 12:21 PM Arnd Bergmann arnd@arndb.de wrote:
How hard would it be to have a private copy of the parts of the core crate that the kernel actually needs? Since Linux is neither quite hosted (using a full libc) nor entirely freestanding (still using some library interfaces), the C implementation on most architectures has a small subset of the libgcc that we ship with the kernel.
I assume the core crate is larger than libgcc, but I don't know how much of it is actually needed here.
It is fairly tied to the compiler version, so it would be a substantial effort to support across a bunch of versions. Instead of that, initially we asked to have some `cfg`s (i.e. conditional compilation) to customize it in the few places we need. We already pass `--cfg no_fp_fmt_parse` for instance.
There were concerns about combinatorial explosion of `cfg`s, so we suggested `cfg(linux_kernel)` or similar instead, though nothing happened so far.
The other option is to at least lint against certain operations, but I think it would be better to have a way to tell the compiler we really don't want them generated to begin with.
Cheers, Miguel
On Fri, Apr 24, 2026 at 11:43 AM Link Mauve linkmauve@linkmauve.fr wrote:
A possible solution would be to change the core crate to not divide u64s, but the last time I tried to do that I couldn’t quite figure out how to do formatting without it, maybe I will just open an issue against Rust.
Yeah, I have some context at:
https://github.com/Rust-for-Linux/linux/issues/2 -> feature(compiler_builtins) and a way to avoid certain intrinsics (f32, f64, i128, u128 and 64-bit divisions/modulos).
We have discussed it at some points with upstream Rust (including related discussions about having more `cfg`s in `core` or a `cfg(linux_kernel)` etc.). I don't think we have an open issue concretely for it, apart from the Clippy one to flag the use the use of the 64-bit division, but if you open a more general one with some details, that would be great.
Thanks!
Cheers, Miguel
On Fri, 24 Apr 2026 11:43:11 +0200 Link Mauve linkmauve@linkmauve.fr wrote:
On Fri, Apr 24, 2026 at 10:14:25AM +0100, David Laight wrote:
On Fri, 24 Apr 2026 11:17:40 +0530 "Mukesh Kumar Chaurasiya (IBM)" mkchauras@gmail.com wrote:
From: Link Mauve linkmauve@linkmauve.fr
The core crate currently depends on these two functions for i64/u64/ i128/u128/core::time::Duration formatting, but we shouldn’t use that in the kernel so let’s panic if they are ever called.
Ugg. Surely you can make it a link-time failure? Or change the underlying code to avoid the divide.
This is currently a link-time failure, which means if any of the core crate or drm_panic_qr are linked in, the kernel will fail to link.
And since we rely on core, that means no kernel can be built on PowerPC without this patch.
A possible solution would be to change the core crate to not divide u64s, but the last time I tried to do that I couldn’t quite figure out how to do formatting without it, maybe I will just open an issue against Rust.
If the problematic code is (effectively) printf("%lld", val) there are much better ways to generate the digit string than repeated 64bit divides. On particular you can use 'multiply by reciprocal' instead. For example see the latest (I think it'll be in 7.1-rc) version of tools/include/nolibc/stdlib.h
David
On Fri, Apr 24, 2026, at 11:43, Link Mauve wrote:
On Fri, Apr 24, 2026 at 10:14:25AM +0100, David Laight wrote:
On Fri, 24 Apr 2026 11:17:40 +0530 "Mukesh Kumar Chaurasiya (IBM)" mkchauras@gmail.com wrote:
From: Link Mauve linkmauve@linkmauve.fr
The core crate currently depends on these two functions for i64/u64/ i128/u128/core::time::Duration formatting, but we shouldn’t use that in the kernel so let’s panic if they are ever called.
Ugg. Surely you can make it a link-time failure? Or change the underlying code to avoid the divide.
This is currently a link-time failure, which means if any of the core crate or drm_panic_qr are linked in, the kernel will fail to link.
And since we rely on core, that means no kernel can be built on PowerPC without this patch.
A possible solution would be to change the core crate to not divide u64s, but the last time I tried to do that I couldn’t quite figure out how to do formatting without it, maybe I will just open an issue against Rust.
I think you just need to rewrite the patch description, it appears that everyone misunderstands what you are doing in the patch:
Like on arm32, normal kernel code will continue to cause a link failure the same way in Rust as it does in C, and your patch does not change that. When you (or Link Mauve) "let's panic", I assume this is was just a mistake in summarizing the logic that turns the unreachable code from the Rust core crate into a runtime assertion since it would be impossible to link the kernel otherwise.
Silently turning a 64-bit division into a panic() for normal code would of course be unacceptable, but that's not what you are doing here.
Arnd
Hi!
On Fri, Apr 24, 2026 at 11:17:40AM +0530, Mukesh Kumar Chaurasiya (IBM) wrote:
The core crate currently depends on these two functions for i64/u64/ i128/u128/core::time::Duration formatting, but we shouldn’t use that in the kernel so let’s panic if they are ever called.
This doesn’t yet fix drm_panic_qr.rs, which also uses __udivdi3 when CONFIG_CC_OPTIMIZE_FOR_SIZE=y, but at least makes the rest of the kernel build on PPC32.
GCC uses calls to functions like even __addsi3 whenever the (sub-)target does not implement some RTL, doesn't have a define_insn and the like for it. When you write a new port you only *have* to implement a very few things, the rest is done in libgcc (you might still have to write some of that for your target, no free lunch etc.)
32-bit PowerPC has no instructions for 64-bit divisions, nor instructions that help implementing it in software. It still very often helps to hand-write machine code for it, it very easily can usually be more than twice as fast for example (for example if the divisor is less than half a word big, the common case -- it can be made tens of times faster then).
There can be many reasons why a GCC backend decides to call a libgcc routine. For __udivdi3 on -m32 rs6000 you'll be good AFAICS :-) (but poisoning functions like you do is a terrible idea in general!)
Segher
On Fri, Apr 24, 2026 at 06:54:05AM -0500, Segher Boessenkool wrote:
Hi!
On Fri, Apr 24, 2026 at 11:17:40AM +0530, Mukesh Kumar Chaurasiya (IBM) wrote:
The core crate currently depends on these two functions for i64/u64/ i128/u128/core::time::Duration formatting, but we shouldn’t use that in the kernel so let’s panic if they are ever called.
This doesn’t yet fix drm_panic_qr.rs, which also uses __udivdi3 when CONFIG_CC_OPTIMIZE_FOR_SIZE=y, but at least makes the rest of the kernel build on PPC32.
GCC uses calls to functions like even __addsi3 whenever the (sub-)target does not implement some RTL, doesn't have a define_insn and the like for it. When you write a new port you only *have* to implement a very few things, the rest is done in libgcc (you might still have to write some of that for your target, no free lunch etc.)
32-bit PowerPC has no instructions for 64-bit divisions, nor instructions that help implementing it in software. It still very often helps to hand-write machine code for it, it very easily can usually be more than twice as fast for example (for example if the divisor is less than half a word big, the common case -- it can be made tens of times faster then).
There can be many reasons why a GCC backend decides to call a libgcc routine. For __udivdi3 on -m32 rs6000 you'll be good AFAICS :-) (but poisoning functions like you do is a terrible idea in general!)
Whoopsie, I forgot to mention:
Approved for trunk.
Segher
On Fri Apr 24, 2026 at 6:47 AM BST, Mukesh Kumar Chaurasiya (IBM) wrote:
From: Link Mauve linkmauve@linkmauve.fr
The core crate currently depends on these two functions for i64/u64/ i128/u128/core::time::Duration formatting, but we shouldn’t use that in the kernel so let’s panic if they are ever called.
This doesn’t yet fix drm_panic_qr.rs, which also uses __udivdi3 when CONFIG_CC_OPTIMIZE_FOR_SIZE=y, but at least makes the rest of the kernel build on PPC32.
Can we always build libcore with `-C opt-level=2` even if `CONFIG_CC_OPTIMIZE_FOR_SIZE` is specified? It feels like a better fix than stubbing things out.
Best, Gary
Signed-off-by: Link Mauve linkmauve@linkmauve.fr Signed-off-by: Mukesh Kumar Chaurasiya (IBM) mkchauras@gmail.com
rust/Makefile | 4 ++++ rust/compiler_builtins.rs | 6 ++++++ 2 files changed, 10 insertions(+)
diff --git a/rust/Makefile b/rust/Makefile index 2a5428a5503d..ee11fba7a03d 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -616,6 +616,10 @@ ifneq ($(or $(CONFIG_ARM64),$(and $(CONFIG_RISCV),$(CONFIG_64BIT))),) __ashrti3 \ __ashlti3 __lshrti3 endif +ifdef CONFIG_PPC32
- redirect-intrinsics += \
__udivdi3 __umoddi3+endif ifdef CONFIG_MODVERSIONS cmd_gendwarfksyms = $(if $(skip_gendwarfksyms),, \ diff --git a/rust/compiler_builtins.rs b/rust/compiler_builtins.rs index dd16c1dc899c..fc6b54636dd5 100644 --- a/rust/compiler_builtins.rs +++ b/rust/compiler_builtins.rs @@ -97,5 +97,11 @@ pub extern "C" fn $ident() { __aeabi_uldivmod, }); +#[cfg(target_arch = "powerpc")] +define_panicking_intrinsics!("`u64` division/modulo should not be used", {
- __udivdi3,
- __umoddi3,
+});
// NOTE: if you are adding a new intrinsic here, you should also add it to // `redirect-intrinsics` in `rust/Makefile`.
From: Link Mauve linkmauve@linkmauve.fr
For now only Big Endian 32-bit PowerPC is supported, as that is the only hardware I have. This has been tested on the Nintendo Wii so far, but I plan on also using it on the GameCube, Wii U and Apple G4.
These changes aren’t the only ones required to get the kernel to compile and link on PowerPC, libcore will also have to be changed to not use integer division to format u64, u128 and core::time::Duration, otherwise __udivdi3() and __umoddi3() will have to be added. I have tested this change by replacing the three implementations with unimplemented!() and it linked just fine.
Signed-off-by: Link Mauve linkmauve@linkmauve.fr Link: https://github.com/Rust-for-Linux/linux/issues/105 Link: https://github.com/linuxppc/issues/issues/451 Acked-by: Gary Guo gary@garyguo.net Signed-off-by: Mukesh Kumar Chaurasiya (IBM) mkchauras@gmail.com --- arch/powerpc/Kconfig | 1 + arch/powerpc/Makefile | 2 ++ rust/Makefile | 4 +++- 3 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index e93df95b79e7..4ac897b650d4 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -285,6 +285,7 @@ config PPC select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_RELIABLE_STACKTRACE select HAVE_RSEQ + select HAVE_RUST if PPC32 select HAVE_SAMPLE_FTRACE_DIRECT if HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS select HAVE_SAMPLE_FTRACE_DIRECT_MULTI if HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS select HAVE_SETUP_PER_CPU_AREA if PPC64 diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index a58b1029592c..589613eaa5dc 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -61,6 +61,8 @@ else KBUILD_LDFLAGS_MODULE += $(objtree)/arch/powerpc/lib/crtsavres.o endif
+KBUILD_RUSTFLAGS += --target=powerpc-unknown-linux-gnu + ifdef CONFIG_CPU_LITTLE_ENDIAN KBUILD_CPPFLAGS += -mlittle-endian KBUILD_LDFLAGS += -EL diff --git a/rust/Makefile b/rust/Makefile index ee11fba7a03d..fd9c1bf026ca 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -400,13 +400,15 @@ bindgen_skip_c_flags := -mno-fp-ret-in-387 -mpreferred-stack-boundary=% \ -fstrict-flex-arrays=% -fmin-function-alignment=% \ -fzero-init-padding-bits=% -mno-fdpic \ -fdiagnostics-show-context -fdiagnostics-show-context=% \ - --param=% --param asan-% -fno-isolate-erroneous-paths-dereference + --param=% --param asan-% -fno-isolate-erroneous-paths-dereference \ + -ffixed-r2 -mmultiple -mno-readonly-in-sdata
# Derived from `scripts/Makefile.clang`. BINDGEN_TARGET_x86 := x86_64-linux-gnu BINDGEN_TARGET_arm64 := aarch64-linux-gnu BINDGEN_TARGET_arm := arm-linux-gnueabi BINDGEN_TARGET_loongarch := loongarch64-linux-gnusf +BINDGEN_TARGET_powerpc := powerpc-linux-gnu BINDGEN_TARGET_um := $(BINDGEN_TARGET_$(SUBARCH)) BINDGEN_TARGET := $(BINDGEN_TARGET_$(SRCARCH))
Enabling rust support for ppc64le.
Tested on pseries Power11: ╰─❯ dmesg | grep rust [ 0.225728] Initialise system trusted keyrings [ 0.270961] rust_minimal: Rust minimal sample (init) [ 0.270968] rust_minimal: Am I built-in? true [ 0.270974] rust_minimal: test_parameter: 1 [ 0.270983] rust_misc_device: Initialising Rust Misc Device Sample [ 0.271012] rust_print: Rust printing macros sample (init) [ 0.271019] rust_print: Emergency message (level 0) without args [ 0.271023] rust_print: Alert message (level 1) without args [ 0.271026] rust_print: Critical message (level 2) without args [ 0.271030] rust_print: Error message (level 3) without args [ 0.271033] rust_print: Warning message (level 4) without args [ 0.271037] rust_print: Notice message (level 5) without args [ 0.271040] rust_print: Info message (level 6) without args [ 0.271043] rust_print: A line that is continued without args [ 0.271054] rust_print: Emergency message (level 0) with args [ 0.271064] rust_print: Alert message (level 1) with args [ 0.271072] rust_print: Critical message (level 2) with args [ 0.271077] rust_print: Error message (level 3) with args [ 0.271083] rust_print: Warning message (level 4) with args [ 0.271091] rust_print: Notice message (level 5) with args [ 0.271097] rust_print: Info message (level 6) with args [ 0.271102] rust_print: A line that is continued with args [ 0.271110] rust_print: 1 [ 0.271113] rust_print: "hello, world" [ 0.271121] rust_print: [samples/rust/rust_print_main.rs:35:5] c = "hello, world" [ 0.271129] rust_print: Arc<dyn Display> says 42 [ 0.271130] rust_print: Arc<dyn Display> says hello, world [ 0.271136] rust_print: "hello, world" [ 0.271198] usbcore: registered new interface driver rust_driver_usb [ 0.271207] rust_faux_driver: Initialising Rust Faux Device Sample [ 0.271227] faux_driver rust-faux-sample-device: Hello from faux device! [ 0.271297] rust_configfs: Rust configfs sample (init)
Reviewed-by: Link Mauve linkmauve@linkmauve.fr Tested-by: Link Mauve linkmauve@linkmauve.fr Reviewed-by: Christophe Leroy (CS GROUP) chleroy@kernel.org Tested-by: Venkat Rao Bagalkote venkat88@linux.ibm.com Link: https://github.com/Rust-for-Linux/linux/issues/105 Link: https://github.com/linuxppc/issues/issues/451 Acked-by: Gary Guo gary@garyguo.net Signed-off-by: Mukesh Kumar Chaurasiya (IBM) mkchauras@gmail.com --- arch/powerpc/Kconfig | 1 + arch/powerpc/Makefile | 7 ++++++- rust/Makefile | 6 ++++++ 3 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 4ac897b650d4..2e3065bce9cd 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -286,6 +286,7 @@ config PPC select HAVE_RELIABLE_STACKTRACE select HAVE_RSEQ select HAVE_RUST if PPC32 + select HAVE_RUST if PPC64 && CPU_LITTLE_ENDIAN select HAVE_SAMPLE_FTRACE_DIRECT if HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS select HAVE_SAMPLE_FTRACE_DIRECT_MULTI if HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS select HAVE_SETUP_PER_CPU_AREA if PPC64 diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 589613eaa5dc..9385db478c59 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -61,7 +61,12 @@ else KBUILD_LDFLAGS_MODULE += $(objtree)/arch/powerpc/lib/crtsavres.o endif
-KBUILD_RUSTFLAGS += --target=powerpc-unknown-linux-gnu +ifdef CONFIG_PPC64 +KBUILD_RUSTFLAGS += --target=powerpc64le-unknown-linux-gnu +KBUILD_RUSTFLAGS += -Ctarget-feature=-mma,-vsx,-hard-float,-altivec +else +KBUILD_RUSTFLAGS += --target=powerpc-unknown-linux-gnu +endif
ifdef CONFIG_CPU_LITTLE_ENDIAN KBUILD_CPPFLAGS += -mlittle-endian diff --git a/rust/Makefile b/rust/Makefile index fd9c1bf026ca..d7b74b209a33 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -408,7 +408,13 @@ BINDGEN_TARGET_x86 := x86_64-linux-gnu BINDGEN_TARGET_arm64 := aarch64-linux-gnu BINDGEN_TARGET_arm := arm-linux-gnueabi BINDGEN_TARGET_loongarch := loongarch64-linux-gnusf + +ifdef CONFIG_PPC64 +BINDGEN_TARGET_powerpc := powerpc64le-linux-gnu +else BINDGEN_TARGET_powerpc := powerpc-linux-gnu +endif + BINDGEN_TARGET_um := $(BINDGEN_TARGET_$(SUBARCH)) BINDGEN_TARGET := $(BINDGEN_TARGET_$(SRCARCH))
linaro-mm-sig@lists.linaro.org