Skip to content

Conversation

@xingxue-ibm
Copy link

@xingxue-ibm xingxue-ibm commented Oct 9, 2025

This PR adds support for powerpc64le Linux. With this implementation, 3 examples under the examples directory and 16 out of 21 unit tests have passed. The following test cases fail and are ignored for this target.

  1. backtrace_traces_to_host in coroutine.rs and on_stack.rs
    The nightly compiler initially failed to generate the eh_frame construct. After updating to 1.92.0-nightly (839222065 2025-10-05), it does generate eh_frame but the test hit a seg-fault in GCC’s unwinder. These tests are disabled for now.

  2. trap_handler, trap_handler_panic, and stack_overflow
    It seems the problem is after signal_handler returns, the control is routed to trap_handler instead of the location where the signal happened. In the powerpc64 ELF ABI, volatile register r12 is used for function linkage and is caller-saved. If a function call before the signal (e.g., println!("Before trap"); in test trap_handler) overwrites r12, e.g. to 0x0, the sigcontext record will also contain 0x0 for r12. When control goes from the signal handler to trap_handler, r12 remains 0x0, When std::panic::catch_unwind, called indirectly by trap_handler, constructs the function address for __rust_try out of r12, it ends up an invalid value, and trigger a seg-fault or illegal instruction.

I'm not very familiar with Valgrind, so it’s currently unsupported on powerpc64 in this implementation. Any insights or guidance would be greatly appreciated.

Note: the test has dependency on the ucontext_t structure from the libc crate. PR Add ucontext_t and {get,set,make,swap}context for powerpc64-linux (cont.) has been approved but not yet included in the libc stable branch and release yet.

Copy link
Owner

@Amanieu Amanieu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did some testing on powerpc64 qemu (with 2b4700e to add the missing ucontext support). Currently this seems to crash even on the base smoke tests. The issue seems to be that function pointers on powerpc actually point to a 3-word descriptor with pc, r2 and r11 values. See https://rust.godbolt.org/z/c9enqqej7 for an example.

This is an initial review, I will do a more in-depth one once the initial problems are fixed.

@xingxue-ibm xingxue-ibm changed the title Add powerpc64 Linux support Add powerpc64le Linux support Oct 17, 2025
@xingxue-ibm
Copy link
Author

xingxue-ibm commented Oct 17, 2025

I did some testing on powerpc64 qemu (with 2b4700e to add the missing ucontext support). Currently this seems to crash even on the base smoke tests. The issue seems to be that function pointers on powerpc actually point to a 3-word descriptor with pc, r2 and r11 values. See https://rust.godbolt.org/z/c9enqqej7 for an example.

This is an initial review, I will do a more in-depth one once the initial problems are fixed.

Thanks for the review, @Amanieu! From the Compiler Explorer session (https://rust.godbolt.org/z/c9enqqej7, it looks like you compiled with --target powerpc64-unknown-linux-gnu, which is for big-endian. The implementation in this PR is intended for little-endian Linux systems such as Red Hat (--target powerpc64le-unknown-linux-gnu). I apologize for the confusion - I should have used powerpc64le in the title and description instead of powerpc64. (The compiler somehow complained about powerpc64le, but the implementation works with target_arch = "powerpc64").

warning: unexpected `cfg` condition value: `powerpc64le`
   --> src/lib.rs:239:13
    |
239 | #![cfg_attr(target_arch = "powerpc64le", feature(asm_experimental_arch))]
    |             ^^^^^^^^^^^^^^-------------
    |                           |
    |                           help: there is a expected value with a similar name: `"powerpc64"`
    |
    = note: expected values for `target_arch` are: `aarch64`, `amdgpu`, `arm`, `arm64ec`, `avr`, `bpf`, `csky`, `hexagon`, `loongarch32`, `loongarch64`, `m68k`, `mips`, `mips32r6`, `mips64`, `mips64r6`, `msp430`, `nvptx64`, `powerpc`, `powerpc64`, `riscv32`, `riscv64`, `s390x`, `sparc`, `sparc64`, `wasm32`, `wasm64`, `x86`, `x86_64`, and `xtensa`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default

The implementation runs 16 out of 21 unit tests successfully on RedHat.

$ cat /etc/redhat-release
Red Hat Enterprise Linux release 8.10 (Ootpa)
$ rustc --version --verbose
rustc 1.92.0-nightly (839222065 2025-10-05)
binary: rustc
commit-hash: 839222065a44ac21c15df68ed2f2f3c0127b0b8e
commit-date: 2025-10-05
host: powerpc64le-unknown-linux-gnu
release: 1.92.0-nightly
LLVM version: 21.1.2
$ cargo test
   Compiling corosensei v0.3.0 (/home/xingxue/corosensei.1)
    Finished `test` profile [unoptimized + debuginfo] target(s) in 1.60s
     Running unittests src/lib.rs (target/debug/deps/corosensei-db2e5dad2186f5df)

running 21 tests
test tests::coroutine::backtrace_traces_to_host ... ignored
test stack::assert_send_sync ... ok
test tests::coroutine::stack_overflow ... ignored
test tests::coroutine::smoke ... ok
test tests::coroutine::stateful ... ok
test tests::coroutine::backward_stack_address - should panic ... ok
test tests::coroutine::trap_handler ... ignored
test tests::coroutine::trap_handler_panic ... ignored
test tests::on_stack::backtrace_traces_to_host ... ignored
test tests::coroutine::panics_propagated - should panic ... ok
test tests::coroutine::force_unwind ... ok
test tests::coroutine::forward_stack_address - should panic ... ok
test tests::coroutine::suspend_and_resume ... ok
test tests::coroutine::panics_propagated_via_parent - should panic ... ok
test tests::coroutine::stack_growth ... ok
test tests::on_stack::smoke ... ok
test tests::coroutine::suspend_and_resume_values ... ok
test tests::on_stack::stack_growth ... ok
test tests::on_stack::backward_stack_address - should panic ... ok
test tests::on_stack::forward_stack_address - should panic ... ok
test tests::on_stack::panics_propagated - should panic ... ok

test result: ok. 16 passed; 0 failed; 5 ignored; 0 measured; 0 filtered out; finished in 0.00s

   Doc-tests corosensei

running 6 tests
test src/coroutine.rs - coroutine::Coroutine::marker2 (line 111) - compile fail ... ok
test src/arch/powerpc64.rs - arch::powerpc64::TrapHandlerRegs (line 632) ... ok
test src/scoped.rs - scoped::ScopedCoroutine (line 70) ... ok
test src/lib.rs - (line 9) ... ok
test src/lib.rs - (line 93) ... ok
test src/lib.rs - (line 146) ... ok

test result: ok. 6 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.51s

$

@Amanieu
Copy link
Owner

Amanieu commented Oct 17, 2025

I see, powerpc64 uses the ELFv1 ABI while powerc64le uses the ELFv2 ABI. You should be able to explicitly handle these with rust-lang/rust#142321. Although for now if might be ok to just compiler_error! on ELFv1 since it's not a supported ABI. We look into supporting it later.

@Amanieu
Copy link
Owner

Amanieu commented Oct 17, 2025

Right, disregard my previous comments on the stack layout, I need to re-read the ABI document in detail.

@Amanieu
Copy link
Owner

Amanieu commented Oct 18, 2025

I've tried to clean up the stack layout for the coroutine here: a783805

Let me know if you think this will work or if I missed anything.

- change the stack layout as per suggestion,
- save/restore the TOC register R2.
@xingxue-ibm
Copy link
Author

I've updated the stack layout as you suggested. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants