-
Notifications
You must be signed in to change notification settings - Fork 13
Add powerpc64 and mips32 architecture support #170
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Add startup code for powerpc64le (ELFv2 ABI) and mipsel (O32 ABI) targets, enabling no_std programs to run on these architectures. PowerPC64 (powerpc64.rs): - _start sets up r2 (TOC pointer) using r12 before calling entry - trap() uses the `trap` instruction - Full thread support scaffolding (clone, thread pointer, TLS) - Relocation support for PIC binaries MIPS32 (mips32.rs): - __start entry point (MIPS convention, not _start) - 8-byte stack alignment with 16-byte O32 save area - trap() uses the `break` instruction - Thread support using rdhwr for thread pointer - Syscall convention: $v0=syscall#, $a0-$a3=args, $a3=error flag Both architectures: - Implement origin-start feature for program startup - Support optimize_for_size feature - Follow existing origin patterns from other architectures Tested with QEMU user-mode emulation (qemu-ppc64le-static, qemu-mipsel-static). Note: QEMU ppc64le has a bug with argv setup for non-glibc binaries, but the startup code itself is correct and works on real hardware.
sunfishcode
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, thanks for contributing these! I have a few comments below, and CI wants a rustfmt.
Also, we should probably mention in README.md that these new targets and also ARM aren't currently tested in CI. I can do that if you prefer though.
That blank line was apparently living rent-free between __start and trap.
We only define __start, not both. The comment was aspirational fiction.
The syscall return value was just sitting there looking decortaive. We only need the error flag from $a3. Note: MIPS cross-compilation is not available on this dev machine, letting CI handle the actual build verification.
Magic numbers... Now using the proper constant from linux_raw_sys like civilized folk.
O32 ABI requires child_tid (5th arg) on stack, which we don't do. Check for CLONE_CHILD_CLEARTID/SETTID upfront and return EOPNOTSUPP.
MIPS got the concise treatment, PPC64 was feeling left out.
88b1401 to
e5b72fa
Compare
|
Thanks, @sunfishcode. I've addressed your review. Unfortunately, my attempt to update the CI matrix failed, I've updated the PR comment with details. Let me know if it works, I'm fine with additional improvements as needed. |
Added a note about arm, powerpc64, and mips32 not being in CI, along with the reasons why (missing rust-std, crate support gaps, and a branch that got lost in the shuffle).
This adds startup code for powerpc64le (ELF v2 ABI) and mipsel (O32 ABI).
Two new arch modules: powerpc64.rs and mips32.rs. Each one has the usual set: entry point, trap(), dynamic_table_addr(), relocation helpers, thread support, etc.
The tricky part on PowerPC64 is r2 (TOC pointer) setup. On ELF v2, r12 contains the entry point address at program start, and we need to compute r2 from it before touching any global/static data:
Without this, any access to static data gives EFAULT because r2 is garbage. Syscalls use the
scinstruction with error indicated by the cr0.SO flag (not negative return like x86).MIPS uses
__startas entry point (MIPS convention). The O32 ABI requires a 16-byte argument save area on the stack, and indirect jumps should go through$t9for PIC compatibility. Thread pointer is accessed via the userlocal register:rdhwr $3, $29.I tested with a minimal no_std binary that reads a static variable and exits with code 42. Both architectures work under QEMU user-mode.
I also tested with a larger application (kv) that does file I/O and string formatting. MIPS works fully including argument parsing. PowerPC64 works the same way except for an argv issue - as far as I can tell from various workarounds and debugging, it's the same correct behavior, but there's a QEMU user-mode bug that corrupts the argv array for non-glibc PPC64LE binaries. The argument strings are placed correctly in memory, but the pointer array has NULLs interleaved. This only affects QEMU emulation, not the origin code itself.
My CI attempts ended poorly:
Tried adding MIPS and PPC64 to CI but both have blockers:
MIPS32 (
mipsel-unknown-linux-gnu):PowerPC64 (
powerpc64le-unknown-linux-gnu):The code for both architectures is still validated by rustfmt and basic compilation in the PR, just not runtime-tested via QEMU.